def setUpClass(cls): struct_si = PymatgenTest.get_structure("Si") vis = MPRelaxSet(struct_si, force_gamma=True) cls.bs_wf = get_wf(struct_si, "bandstructure.yaml", vis=vis, common_params={"vasp_cmd": "test_VASP"}) cls.bsboltz_wf = get_wf(struct_si, "bandstructure_boltztrap.yaml", vis=vis)
def wf_scan_opt(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) user_incar_settings = c.get("USER_INCAR_SETTINGS", {}) half_kpts = c.get("HALF_KPOINTS_FIRST_RELAX", HALF_KPOINTS_FIRST_RELAX) ediffg = user_incar_settings.get("EDIFFG", -0.05) wf = get_wf(structure, "optimize_only.yaml", vis=MVLScanRelaxSet(structure, user_incar_settings=user_incar_settings), common_params={ "vasp_cmd": vasp_cmd, "db_file": db_file }) wf = use_custodian(wf, custodian_params={ "ediffg": ediffg, "max_force_threshold": 0, "half_kpts_first_relax": half_kpts, "job_type": "metagga_opt_run", "vasp_cmd": vasp_cmd }) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) if c.get("REMOVE_WAVECAR", REMOVE_WAVECAR): wf = clean_up_files(wf) return wf
def wf_scan_opt(structure, c=None): """ Structure optimization using the SCAN metaGGA functional. This workflow performs a 2-step optmization. The first step is a conventional GGA run and serves to precondition the geometry and wavefunctions. The second step is a SCAN structure optimization. The first optimization is force converged with EDIFFG = -0.05, and the second optimization is force converged with EDIFFG=-0.02. """ c = c or {} user_incar_settings = c.get("USER_INCAR_SETTINGS", {}) vdw = c.get("vdw") bandgap = c.get("bandgap", 0) wf = get_wf( structure, "SCAN_optimization.yaml", vis=MPScanRelaxSet(structure, user_incar_settings=user_incar_settings, vdw=vdw, bandgap=bandgap), params=[{ "name": "SCAN optimization" }], ) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_single_Vasp_dbinsertion(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={ "vasp_cmd": VASP_CMD, "db_file": ">>db_file<<" }) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) # add an msonable object to additional fields my_wf.fws[0].tasks[-1]['additional_fields'].update( {"test_additional_field": self.struct_si}) self.lp.add_wf(my_wf) # run the workflow rapidfire(self.lp, fworker=_fworker) d = self.get_task_collection().find_one() self._check_run(d, mode="structure optimization") self._check_run(d, mode="additional field") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def test_chgcar_db_read(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "static_only.yaml", vis=MPStaticSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD, "db_file": ">>db_file<<"}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) # set the flags for storing charge densties my_wf.fws[0].tasks[-1]["parse_chgcar"] = True my_wf.fws[0].tasks[-1]["parse_aeccar"] = True self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire(self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) d = self.get_task_collection().find_one() self._check_run(d, mode="static") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()])) chgcar_fs_id = d["calcs_reversed"][0]["chgcar_fs_id"] accar0_fs_id = d["calcs_reversed"][0]["aeccar0_fs_id"] accar2_fs_id = d["calcs_reversed"][0]["aeccar2_fs_id"] self.assertTrue(bool(chgcar_fs_id)) self.assertTrue(bool(accar0_fs_id)) self.assertTrue(bool(accar2_fs_id))
def wf_bandstructure_plus_boltztrap(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) params = [] for x in range(4): # everything but BoltzTrap task params.append({"vasp_cmd": vasp_cmd, "db_file": db_file}) params.append({"db_file": db_file}) wf = get_wf(structure, "bandstructure_boltztrap.yaml", vis=MPRelaxSet(structure, force_gamma=True), params=params) wf = add_common_powerups(wf, c) if c.get("SMALLGAP_KPOINT_MULTIPLY", SMALLGAP_KPOINT_MULTIPLY): wf = add_small_gap_multiply(wf, 0.5, 5, "static") wf = add_small_gap_multiply(wf, 0.5, 5, "nscf") if c.get("STABILITY_CHECK", STABILITY_CHECK): wf = add_stability_check(wf, fw_name_constraint="structure optimization") if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_single_Vasp_dbinsertion(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={ "vasp_cmd": VASP_CMD, "db_file": ">>db_file<<" }) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire( self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) d = self.get_task_collection().find_one() self._check_run(d, mode="structure optimization") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def wf_bandstructure_plus_hse(structure, gap_only=True, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) if gap_only: wf_src_name = "bandstructure_hsegap.yaml" else: wf_src_name = "bandstructure_hse.yaml" wf = get_wf(structure, wf_src_name, vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}) wf = add_common_powerups(wf, c) if c.get("SMALLGAP_KPOINT_MULTIPLY", SMALLGAP_KPOINT_MULTIPLY): wf = add_small_gap_multiply(wf, 0.5, 5, "static") wf = add_small_gap_multiply(wf, 0.5, 5, "nscf") if c.get("STABILITY_CHECK", STABILITY_CHECK): wf = add_stability_check(wf, fw_name_constraint="structure optimization") if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def wf_bandstructure_plus_boltztrap(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) params = [] for x in range(4): params.append({"vasp_cmd": vasp_cmd, "db_file": db_file}) params.append({"db_file": db_file}) wf = get_wf(structure, "bandstructure_boltztrap.yaml", vis=MPRelaxSet(structure, force_gamma=True), params=params) wf = add_common_powerups(wf, c) if c.get("SMALLGAP_KPOINT_MULTIPLY", SMALLGAP_KPOINT_MULTIPLY): wf = add_small_gap_multiply(wf, 0.5, 5, "static") wf = add_small_gap_multiply(wf, 0.5, 5, "nscf") if c.get("STABILITY_CHECK", STABILITY_CHECK): wf = add_stability_check(wf, fw_name_constraint="structure optimization") if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_bandgap_check_Vasp(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "bandstructure.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD, "db_file": ">>db_file<<"}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) my_wf = add_namefile(my_wf) # add a slug of fw-name to output files my_wf = add_bandgap_check(my_wf, check_bandgap_params={"max_gap": 0.1}, fw_name_constraint="structure optimization") self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire(self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) # structure optimization should be completed self.assertEqual(self.lp.fireworks.find_one( {"name": "Si-structure optimization"}, {"state": 1})["state"], "COMPLETED") self.assertEqual(self.lp.fireworks.find_one( {"name": "Si-static"}, {"state": 1})["state"], "DEFUSED")
def wf_bandstructure_hse(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) wf_src_name = "bandstructure_hse_full.yaml" wf = get_wf(structure, wf_src_name, vis=MPHSERelaxSet(structure, force_gamma=True), common_params={ "vasp_cmd": vasp_cmd, "db_file": db_file }) wf = add_common_powerups(wf, c) if c.get("SMALLGAP_KPOINT_MULTIPLY", SMALLGAP_KPOINT_MULTIPLY): wf = add_small_gap_multiply(wf, 0.5, 5, "static") if c.get("STABILITY_CHECK", STABILITY_CHECK): wf = add_stability_check(wf, fw_name_constraint="structure optimization") if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def wf_bandstructure_no_opt(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) wf = get_wf( structure, "bandstructure_no_opt.yaml", vis=MPStaticSet(structure, force_gamma=True), common_params={ "vasp_cmd": vasp_cmd, "db_file": db_file }, ) wf = add_common_powerups(wf, c) if c.get("SMALLGAP_KPOINT_MULTIPLY", SMALLGAP_KPOINT_MULTIPLY): wf = add_small_gap_multiply(wf, 0.5, 5, "static") wf = add_small_gap_multiply(wf, 0.5, 5, "nscf") if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_single_Vasp_dbinsertion(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD, "db_file": ">>db_file<<"}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) # add an msonable object to additional fields my_wf.fws[0].tasks[-1]['additional_fields'].update( {"test_additional_field": self.struct_si}) self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire(self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) d = self.get_task_collection().find_one() self._check_run(d, mode="structure optimization") self._check_run(d, mode="additional field") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def wf_structure_optimization(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) user_incar_settings = c.get("USER_INCAR_SETTINGS") wf = get_wf( structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True, user_incar_settings=user_incar_settings), common_params={ "vasp_cmd": vasp_cmd, "db_file": db_file }, ) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_bandgap_check_Vasp(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "bandstructure.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={ "vasp_cmd": VASP_CMD, "db_file": ">>db_file<<" }) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) my_wf = add_namefile(my_wf) # add a slug of fw-name to output files my_wf = add_bandgap_check(my_wf, check_bandgap_params={"max_gap": 0.1}, fw_name_constraint="structure optimization") self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire(self.lp, fworker=_fworker) # structure optimization should be completed self.assertEqual( self.lp.fireworks.find_one({"name": "Si-structure optimization"}, {"state": 1})["state"], "COMPLETED") self.assertEqual( self.lp.fireworks.find_one({"name": "Si-static"}, {"state": 1})["state"], "DEFUSED")
def test_trackers(self): # add the workflow structure = self.struct_si my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) my_wf = add_trackers(my_wf) self.lp.add_wf(my_wf) # run the workflow rapidfire(self.lp, fworker=_fworker) for x in self.lp.get_tracker_data(1): for t in x["trackers"]: self.assertGreater(len(t.content.split("\n")), 20) wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def test_SCAN_large_bandgap(self): # A structure with a large bandgap (LiF) should result in KSPACING # hitting the maximum allowed value of 0.44 structure = Structure.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiF/inputs", "POSCAR")) my_wf = get_wf(structure, "SCAN_optimization.yaml", vis=MPScanRelaxSet(structure), common_params={"vasp_cmd": VASP_CMD}) self._run_scan_relax(my_wf, "SCAN_structure_optimization_LiF") # Check INCAR.orig generated by the InputSet incar_orig = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.orig.gz")) ref_incar = Incar.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiF/inputs", "INCAR.orig")) for p in incar_orig.keys(): if p == "MAGMOM": # Ignore MAGMOM b/c structure initialized from POSCAR cannot have a MAGMOM pass else: self.assertEqual(incar_orig[p], ref_incar[p]) # Check INCAR.relax1 generated by the Workflow incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax1.gz")) self.assertEqual(incar["METAGGA"], "None") self.assertEqual(incar["EDIFFG"], -0.05) self.assertEqual(incar["LWAVE"], False) # Check INCAR.relax2 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax2.gz")) self.assertEqual(incar["METAGGA"], "None") self.assertEqual(incar["LWAVE"], True) self.assertEqual(incar["NSW"], 0) self.assertEqual(incar["EDIFFG"], -0.05) self.assertEqual(incar["ICHARG"], 1) self.assertEqual(incar["ISTART"], 0) # Check INCAR.relax3 for the correct kspacing incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax3.gz")) for p in incar.keys(): if p == "KSPACING": self.assertEqual(incar[p], 0.44) elif p == "ICHARG" or p == "ISTART": self.assertEqual(incar[p], 1) elif p == "ISMEAR": self.assertEqual(incar[p], -5) elif p == "SIGMA": self.assertEqual(incar[p], 0.05) else: self.assertEqual(incar_orig[p], incar[p])
def test_SCAN_small_bandgap(self): # A structure with a small bandgap (LiH) should result in a KSPACING # value of 0.351275 structure = Structure.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiH/inputs", "POSCAR")) my_wf = get_wf(structure, "SCAN_optimization.yaml", vis=MPScanRelaxSet(structure), common_params={"vasp_cmd": VASP_CMD}) self._run_scan_relax(my_wf, "SCAN_structure_optimization_LiH") # Check INCAR.orig incar_orig = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.orig.gz")) ref_incar = Incar.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiH/inputs", "INCAR.orig")) for p in incar_orig.keys(): if p == "MAGMOM": # Ignore MAGMOM b/c structure initialized from POSCAR cannot have a MAGMOM pass else: self.assertEqual(incar_orig[p], ref_incar[p]) # Check INCAR.relax1 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax1.gz")) self.assertEqual(incar["METAGGA"], "None") self.assertEqual(incar["EDIFFG"], -0.05) self.assertEqual(incar["LWAVE"], False) # Check INCAR.relax2 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax2.gz")) self.assertEqual(incar["METAGGA"], "None") self.assertEqual(incar["LWAVE"], True) self.assertEqual(incar["NSW"], 0) self.assertEqual(incar["EDIFFG"], -0.05) self.assertEqual(incar["ICHARG"], 1) self.assertEqual(incar["ISTART"], 0) # Check INCAR.relax3 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax3.gz")) for p in incar.keys(): if p == "KSPACING": self.assertAlmostEqual(incar[p], 0.351275, 4) elif p == "ICHARG" or p == "ISTART": self.assertEqual(incar[p], 1) elif p == "ISMEAR": self.assertEqual(incar[p], -5) elif p == "SIGMA": self.assertEqual(incar[p], 0.05) else: self.assertEqual(incar_orig[p], incar[p])
def test_SCAN_large_bandgap(self): # A structure with a large bandgap (LiF) should result in KSPACING # hitting the maximum allowed value of 0.44 structure = Structure.from_file( os.path.join(reference_dir, "PBESol_pre_opt_for_SCAN_LiF/inputs", "POSCAR")) my_wf = get_wf(structure, "metagga_optimization.yaml") fw_ids = self._run_scan_relax(my_wf, "LiF") # Check PBESol INCAR ref_incar = Incar.from_file( os.path.join(reference_dir, "PBESol_pre_opt_for_SCAN_LiF/inputs", "INCAR")) incar = Incar.from_file( os.path.join(self._get_launch_dir()[0], "INCAR.gz")) for p in incar.keys(): if p == "KSPACING": self.assertEqual(incar[p], 0.22) elif p == "ICHARG" or p == "ISTART": self.assertEqual(incar[p], 1) elif p == "METAGGA": self.assertEqual(incar[p], "None") elif p == "GGA": self.assertEqual(incar[p], "Ps") elif p == "EDIFFG": self.assertEqual(incar[p], -0.05) elif p == "MAGMOM": # Ignore MAGMOM b/c structure initialized from POSCAR cannot have a MAGMOM pass else: self.assertEqual(incar[p], ref_incar[p]) # Check SCAN INCAR ref_incar = Incar.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiF/inputs", "INCAR")) incar = Incar.from_file( os.path.join(self._get_launch_dir()[1], "INCAR.gz")) for p in incar.keys(): if p == "KSPACING": self.assertEqual(incar[p], 0.44) elif p == "SIGMA": self.assertEqual(incar[p], 0.05) elif p == "ICHARG": self.assertEqual(incar[p], 1) else: self.assertEqual(incar[p], ref_incar[p]) # get a fw that can be used to identify the workflow fw_id = list(fw_ids.values())[0] # check workflow finished without error wf = self.lp.get_wf_by_fw_id(fw_id) is_completed = [s == "COMPLETED" for s in wf.fw_states.values()] self.assertTrue(all(is_completed))
def test_SCAN_with_vdw(self): # Verify appropriate changes to the INCAR when VdW is enabled # VdW should be off for relax1 (GGA) and re-enabled for relax2 (SCAN) structure = Structure.from_file(os.path.join(reference_dir, "SCAN_structure_optimization_LiF_vdw/inputs", "POSCAR")) my_wf = get_wf(structure, "SCAN_optimization.yaml", vis=MPScanRelaxSet(structure, vdw="rvv10"), common_params={"vasp_cmd": VASP_CMD, "vdw_kernel_dir": os.path.join(reference_dir, "SCAN_structure_optimization_LiF_vdw/inputs")}) self._run_scan_relax(my_wf, "SCAN_structure_optimization_LiF_vdw") # Check INCAR.orig incar_orig = Incar.from_file(os.path.join(self._get_launch_dir(), "INCAR.orig.gz")) ref_incar = Incar.from_file(os.path.join(reference_dir, "SCAN_structure_optimization_LiF_vdw/inputs", "INCAR.orig")) for p in incar_orig.keys(): if p == "MAGMOM": # Ignore MAGMOM b/c structure initialized from POSCAR cannot have a MAGMOM pass else: self.assertEqual(incar_orig[p], ref_incar[p]) # Check INCAR.relax1 incar = Incar.from_file(os.path.join(self._get_launch_dir(), "INCAR.relax1.gz")) self.assertIsNone(incar.get("LUSE_VDW", None)) self.assertIsNone(incar.get("BPARAM", None)) self.assertEqual(incar["METAGGA"], "None") self.assertEqual(incar["EDIFFG"], -0.05) self.assertEqual(incar["LWAVE"], False) # Check INCAR.relax2 incar = Incar.from_file(os.path.join(self._get_launch_dir(), "INCAR.relax2.gz")) self.assertEqual(incar["METAGGA"], "None") self.assertEqual(incar["LWAVE"], True) self.assertEqual(incar["NSW"], 0) self.assertEqual(incar["EDIFFG"], -0.05) self.assertEqual(incar["ICHARG"], 1) self.assertEqual(incar["ISTART"], 0) # Check INCAR.relax3 incar = Incar.from_file(os.path.join(self._get_launch_dir(), "INCAR.relax3.gz")) for p in incar.keys(): if p == "KSPACING": self.assertEqual(incar[p], 0.44) elif p == "ICHARG" or p == "ISTART": self.assertEqual(incar[p], 1) elif p == "ISMEAR": self.assertEqual(incar[p], -5) elif p == "SIGMA": self.assertEqual(incar[p], 0.05) elif p == "MAGMOM": # Ignore MAGMOM b/c structure initialized from POSCAR cannot have a MAGMOM pass else: self.assertEqual(incar_orig[p], incar[p])
def wf_thermal_expansion(structure, c=None): """ Thermal expansion coefficient workflow from the given structure and config dict. Args: structure (Structure): input structure c (dict): workflow config dict Returns: Workflow """ c = c or {} eos = c.get("EOS", "vinet") vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) pressure = c.get("PRESSURE", 0.0) user_kpoints_settings = {"grid_density": 7000} # 10 deformations deformations = [(np.identity(3) * (1 + x)).tolist() for x in np.linspace(-0.1, 0.1, 10)] tag = "thermal_expansion group: >>{}<<".format(str(uuid4())) # input set for structure optimization vis_relax = MPRelaxSet(structure, force_gamma=True) v = vis_relax.as_dict() v.update({"user_kpoints_settings": user_kpoints_settings}) vis_relax = vis_relax.__class__.from_dict(v) # optimization only workflow wf = get_wf(structure, "optimize_only.yaml", params=[{"vasp_cmd": vasp_cmd, "db_file": db_file, "name": "{} structure optimization".format(tag)}], vis=vis_relax) wf_thermal = get_wf_thermal_expansion(structure, user_kpoints_settings=user_kpoints_settings, deformations=deformations, vasp_cmd=vasp_cmd, db_file=db_file, eos=eos, pressure=pressure, tag=tag) # chain it wf.append_wf(wf_thermal, wf.leaf_fw_ids) wf = add_modify_incar(wf, modify_incar_params={"incar_update": {"ENCUT": 600, "EDIFF": 1e-6}}) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def wf_scan_opt(structure, c=None): """ Structure optimization using the SCAN metaGGA functional. This workflow performs a 2-step optmization. The first step is a GGA structure optimization using the PBESol functional that serves to precondition the geometry and charge density. The second step is a SCAN structure optimization. The first optimization is force converged with EDIFFG = -0.05, and the second optimization is force converged with EDIFFG=-0.02. The bandgap from the first step is used to update the KSPACING parameter, which sets the appropriate number of k-points for the subsequent SCAN calculation. """ c = c or {} # override the default R2SCAN functional with SCAN vasp_input_set_params = {"user_incar_settings": {"METAGGA": "SCAN"}} if c.get("USER_INCAR_SETTINGS"): vasp_input_set_params["user_incar_settings"] = c.get( "USER_INCAR_SETTINGS") # if the user has supplied METAGGA, respect that setting instead if not vasp_input_set_params["user_incar_settings"].get("METAGGA"): vasp_input_set_params["user_incar_settings"]["METAGGA"] = "SCAN" if c.get("vdw"): vasp_input_set_params["vdw"] = c.get("vdw") if c.get("bandgap"): vasp_input_set_params["bandgap"] = c.get("bandgap") wf = get_wf( structure, "metagga_optimization.yaml", # override the default FW name to reflect the SCAN functional params=[{}, { "name": "SCAN structure optimization" }], common_params={"vasp_input_set_params": vasp_input_set_params}, ) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_bandstructure_Vasp(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "bandstructure.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={ "vasp_cmd": VASP_CMD, "db_file": ">>db_file<<" }) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) my_wf = add_namefile(my_wf) # add a slug of fw-name to output files self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire( self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) # make sure the structure relaxation ran OK d = self.get_task_collection().find_one( {"task_label": "structure optimization"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="structure optimization") # make sure the static run ran OK d = self.get_task_collection().find_one({"task_label": "static"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="static") # make sure the uniform run ran OK d = self.get_task_collection().find_one({"task_label": "nscf uniform"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="nscf uniform") # make sure the uniform run ran OK d = self.get_task_collection().find_one({"task_label": "nscf line"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="nscf line") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def wf_dielectric_constant(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) wf = get_wf(structure, "dielectric_constant.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def wf_nmr(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) wf = get_wf(structure, "nmr.yaml", common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def wf_static(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) wf = get_wf(structure, "static_only.yaml", vis=MPStaticSet(structure), common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_SCAN_incar_override(self): # user incar settings should be passed all the way through the workflow structure = Structure.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiH/inputs", "POSCAR")) my_wf = get_wf(structure, "SCAN_optimization.yaml", vis=MPScanRelaxSet(structure, user_potcar_functional="PBE_52", user_incar_settings={ "NSW": 10, "SYMPREC": 1e-6, "SIGMA": 0.1 }), common_params={"vasp_cmd": VASP_CMD}) self._run_scan_relax(my_wf, "SCAN_structure_optimization_LiH") # Check INCAR.orig incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.orig.gz")) self.assertEqual(incar["NSW"], 10) self.assertEqual(incar["SYMPREC"], 1e-6) self.assertEqual(incar["SIGMA"], 0.1) # Check INCAR.relax1 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax1.gz")) self.assertEqual(incar["NSW"], 10) self.assertEqual(incar["SYMPREC"], 1e-6) self.assertEqual(incar["SIGMA"], 0.1) # Check INCAR.relax2 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax2.gz")) self.assertEqual(incar["NSW"], 0) self.assertEqual(incar["SYMPREC"], 1e-6) self.assertEqual(incar["SIGMA"], 0.1) # Check INCAR.relax3 incar = Incar.from_file( os.path.join(self._get_launch_dir(), "INCAR.relax3.gz")) self.assertEqual(incar["NSW"], 10) self.assertEqual(incar["SYMPREC"], 1e-6) self.assertEqual(incar["SIGMA"], 0.1)
def wf_elastic_constant(structure, c=None, order=2, sym_reduce=False): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) uis_optimize = {"ENCUT": 700, "EDIFF": 1e-6, "LAECHG": False} if order > 2: uis_optimize.update({"EDIFF": 1e-10, "EDIFFG": -0.001, "ADDGRID": True, "LREAL": False, "ISYM": 0}) # This ensures a consistent k-point mesh across all calculations # We also turn off symmetry to prevent VASP from changing the # mesh internally kpts_settings = Kpoints.automatic_density(structure, 40000, force_gamma=True) stencils = np.linspace(-0.075, 0.075, 7) else: kpts_settings = {'grid_density': 7000} stencils = None uis_static = uis_optimize.copy() uis_static.update({'ISIF': 2, 'IBRION': 2, 'NSW': 99, 'ISTART': 1, "PREC": "High"}) # input set for structure optimization vis_relax = MPRelaxSet(structure, force_gamma=True, user_incar_settings=uis_optimize, user_kpoints_settings=kpts_settings) # optimization only workflow wf = get_wf(structure, "optimize_only.yaml", vis=vis_relax, params=[{"vasp_cmd": vasp_cmd, "db_file": db_file, "name": "elastic structure optimization"}]) vis_static = MPStaticSet(structure, force_gamma=True, lepsilon=False, user_kpoints_settings=kpts_settings, user_incar_settings=uis_static) # deformations wflow for elasticity calculation wf_elastic = get_wf_elastic_constant(structure, vasp_cmd=vasp_cmd, db_file=db_file, order=order, stencils=stencils, copy_vasp_outputs=True, vasp_input_set=vis_static, sym_reduce=sym_reduce) wf.append_wf(wf_elastic, wf.leaf_fw_ids) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def wf_structure_optimization(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) user_incar_settings = c.get("USER_INCAR_SETTINGS") wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True, user_incar_settings=user_incar_settings), common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_single_Vasp_dbinsertion(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD, "db_file": ">>db_file<<"}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire(self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) d = self._get_task_collection().find_one() self._check_run(d, mode="structure optimization")
def test_single_Vasp(self): # add the workflow structure = self.struct_si my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) self.lp.add_wf(my_wf) # run the workflow rapidfire(self.lp) fw = self.lp.get_fw_by_id(1) with open(os.path.join(fw.launches[-1].launch_dir, "task.json")) as f: d = json.load(f) self._check_run(d, mode="structure optimization")
def test_single_Vasp(self): # add the workflow structure = self.struct_si my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) self.lp.add_wf(my_wf) # run the workflow rapidfire(self.lp, fworker=_fworker) d = self.get_task_collection().find_one({"task_label": "structure optimization"}) self._check_run(d, mode="structure optimization") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def test_SCAN_incar_override(self): # user incar settings should be passed all the way through the workflow structure = Structure.from_file( os.path.join(reference_dir, "PBESol_pre_opt_for_SCAN_LiH/inputs", "POSCAR")) my_wf = get_wf(structure, "metagga_optimization.yaml", common_params={ "vasp_input_set_params": { "user_potcar_functional": "PBE_52", "user_incar_settings": { "NSW": 10, "SYMPREC": 1e-6, "SIGMA": 0.1 } } }) fw_ids = self._run_scan_relax(my_wf, "LiH") # Check PBESol INCAR incar1 = Incar.from_file( os.path.join(self._get_launch_dir()[0], "INCAR.gz")) self.assertEqual(incar1["NSW"], 10) self.assertEqual(incar1["SYMPREC"], 1e-6) self.assertEqual(incar1["SIGMA"], 0.1) # Check SCAN INCAR incar2 = Incar.from_file( os.path.join(self._get_launch_dir()[1], "INCAR.gz")) self.assertEqual(incar2["NSW"], 10) self.assertEqual(incar2["SYMPREC"], 1e-6) self.assertEqual(incar2["SIGMA"], 0.1) # get a fw that can be used to identify the workflow fw_id = list(fw_ids.values())[0] # check workflow finished without error wf = self.lp.get_wf_by_fw_id(fw_id) is_completed = [s == "COMPLETED" for s in wf.fw_states.values()] self.assertTrue(all(is_completed))
def wf_r2scan_opt(structure, c=None): """ Structure optimization using the R2SCAN metaGGA functional. This workflow performs a 2-step optmization. The first step is a GGA structure optimization using the PBESol functional that serves to precondition the geometry and charge density. The second step is a R2SCAN structure optimization. The first optimization is force converged with EDIFFG = -0.05, and the second optimization is force converged with EDIFFG=-0.02. The bandgap from the first step is used to update the KSPACING parameter, which sets the appropriate number of k-points for the subsequent R2SCAN calculation. """ c = c or {} vasp_input_set_params = {} if c.get("USER_INCAR_SETTINGS"): vasp_input_set_params["user_incar_settings"] = c.get( "USER_INCAR_SETTINGS") if c.get("vdw"): vasp_input_set_params["vdw"] = c.get("vdw") if c.get("bandgap"): vasp_input_set_params["bandgap"] = c.get("bandgap") wf = get_wf( structure, "metagga_optimization.yaml", common_params={"vasp_input_set_params": vasp_input_set_params}, ) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf
def test_trackers(self): # add the workflow structure = self.struct_si my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) my_wf = add_trackers(my_wf) self.lp.add_wf(my_wf) # run the workflow rapidfire(self.lp) for x in self.lp.get_tracker_data(1): for t in x["trackers"]: self.assertGreater(len(t.content.split("\n")), 20)
def test_bandstructure_Vasp(self): # add the workflow structure = self.struct_si # instructs to use db_file set by FWorker, see env_chk my_wf = get_wf(structure, "bandstructure.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD, "db_file": ">>db_file<<"}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) my_wf = add_namefile(my_wf) # add a slug of fw-name to output files self.lp.add_wf(my_wf) # run the workflow # set the db_file variable rapidfire(self.lp, fworker=FWorker(env={"db_file": os.path.join(db_dir, "db.json")})) # make sure the structure relaxation ran OK d = self.get_task_collection().find_one({"task_label": "structure optimization"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="structure optimization") # make sure the static run ran OK d = self.get_task_collection().find_one({"task_label": "static"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="static") # make sure the uniform run ran OK d = self.get_task_collection().find_one({"task_label": "nscf uniform"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="nscf uniform") # make sure the uniform run ran OK d = self.get_task_collection().find_one({"task_label": "nscf line"}, sort=[("_id", DESCENDING)]) self._check_run(d, mode="nscf line") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def test_single_Vasp(self): # add the workflow structure = self.struct_si my_wf = get_wf(structure, "optimize_only.yaml", vis=MPRelaxSet(structure, force_gamma=True), common_params={"vasp_cmd": VASP_CMD}) if not VASP_CMD: my_wf = use_fake_vasp(my_wf, ref_dirs_si) else: my_wf = use_custodian(my_wf) self.lp.add_wf(my_wf) # run the workflow rapidfire(self.lp) fw = self.lp.get_fw_by_id(1) with open(os.path.join(fw.launches[-1].launch_dir, "task.json")) as f: d = json.load(f) self._check_run(d, mode="structure optimization") wf = self.lp.get_wf_by_fw_id(1) self.assertTrue(all([s == 'COMPLETED' for s in wf.fw_states.values()]))
def wf_scan_opt(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) user_incar_settings = c.get("USER_INCAR_SETTINGS", {}) half_kpts = c.get("HALF_KPOINTS_FIRST_RELAX", HALF_KPOINTS_FIRST_RELAX) ediffg = user_incar_settings.get("EDIFFG", -0.05) wf = get_wf( structure, "optimize_only.yaml", vis=MVLScanRelaxSet( structure, user_incar_settings=user_incar_settings), common_params={ "vasp_cmd": vasp_cmd, "db_file": db_file }) wf = use_custodian( wf, custodian_params={ "ediffg": ediffg, "max_force_threshold": 0, "half_kpts_first_relax": half_kpts, "job_type": "metagga_opt_run", "db_file": db_file, "vasp_cmd": vasp_cmd }) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) if c.get("REMOVE_WAVECAR", REMOVE_WAVECAR): wf = clean_up_files(wf) return wf
def get_wf_magnetic_deformation(structure, c=None, vis=None): """ Minimal workflow to obtain magnetic deformation proxy, as defined by Bocarsly et al. 2017, doi: 10.1021/acs.chemmater.6b04729 Args: structure: input structure, must be structure with magnetic elements, such that pymatgen will initalize ferromagnetic input by default -- see MPRelaxSet.yaml for list of default elements c: Workflow config dict, in the same format as in presets/core.py and elsewhere in atomate vis: A VaspInputSet to use for the first FW Returns: Workflow """ if not structure.is_ordered: raise ValueError( "Please obtain an ordered approximation of the input structure." ) structure = structure.get_primitive_structure(use_site_props=True) # using a uuid for book-keeping, # in a similar way to other workflows uuid = str(uuid4()) c_defaults = {"vasp_cmd": VASP_CMD, "db_file": DB_FILE} if c: c.update(c_defaults) else: c = c_defaults wf = get_wf(structure, "magnetic_deformation.yaml", common_params=c, vis=vis) fw_analysis = Firework( MagneticDeformationToDB( db_file=DB_FILE, wf_uuid=uuid, to_db=c.get("to_db", True) ), name="MagneticDeformationToDB", ) wf.append_wf(Workflow.from_Firework(fw_analysis), wf.leaf_fw_ids) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) wf = add_additional_fields_to_taskdocs( wf, { "wf_meta": { "wf_uuid": uuid, "wf_name": "magnetic_deformation", "wf_version": __magnetic_deformation_wf_version__, } }, ) return wf
def get_wf_magnetic_deformation(structure, c=None, vis=None): """ Minimal workflow to obtain magnetic deformation proxy, as defined by Bocarsly et al. 2017, doi: 10.1021/acs.chemmater.6b04729 Args: structure: input structure, must be structure with magnetic elements, such that pymatgen will initalize ferromagnetic input by default -- see MPRelaxSet.yaml for list of default elements c: Workflow config dict, in the same format as in presets/core.py and elsewhere in atomate vis: A VaspInputSet to use for the first FW Returns: Workflow """ if not structure.is_ordered: raise ValueError( "Please obtain an ordered approximation of the input structure.") structure = structure.get_primitive_structure(use_site_props=True) # using a uuid for book-keeping, # in a similar way to other workflows uuid = str(uuid4()) c_defaults = {"vasp_cmd": VASP_CMD, "db_file": DB_FILE} if c: c.update(c_defaults) else: c = c_defaults wf = get_wf(structure, "magnetic_deformation.yaml", common_params=c, vis=vis) fw_analysis = Firework( MagneticDeformationToDb(db_file=DB_FILE, wf_uuid=uuid, to_db=c.get("to_db", True)), name="MagneticDeformationToDb", ) wf.append_wf(Workflow.from_Firework(fw_analysis), wf.leaf_fw_ids) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) wf = add_additional_fields_to_taskdocs( wf, { "wf_meta": { "wf_uuid": uuid, "wf_name": "magnetic_deformation", "wf_version": __magnetic_deformation_wf_version__, } }, ) return wf
def test_SCAN_with_vdw(self): # Verify appropriate changes to the INCAR when VdW is enabled # VdW should be off for relax1 (GGA) and re-enabled for relax2 (SCAN) structure = Structure.from_file( os.path.join(reference_dir, "PBESol_pre_opt_for_SCAN_LiF_vdw/inputs", "POSCAR")) my_wf = get_wf(structure, "metagga_optimization.yaml", common_params={ "vasp_input_set_params": { "vdw": "rVV10" }, "vdw_kernel_dir": os.path.join( reference_dir, "PBESol_pre_opt_for_SCAN_LiF_vdw/inputs") }) fw_ids = self._run_scan_relax(my_wf, "LiF_vdw") # Check PBESol INCAR ref_incar = Incar.from_file( os.path.join(reference_dir, "PBESol_pre_opt_for_SCAN_LiF_vdw/inputs", "INCAR")) incar = Incar.from_file( os.path.join(self._get_launch_dir()[0], "INCAR.gz")) self.assertIsNone(incar.get("LUSE_VDW", None)) self.assertIsNone(incar.get("BPARAM", None)) for p in incar.keys(): if p == "KSPACING": self.assertEqual(incar[p], 0.22) elif p == "ICHARG": self.assertEqual(incar[p], 1) elif p == "METAGGA": self.assertEqual(incar[p], "None") elif p == "GGA": self.assertEqual(incar[p], "Ps") elif p == "EDIFFG": self.assertEqual(incar[p], -0.05) elif p == "MAGMOM": # Ignore MAGMOM b/c structure initialized from POSCAR cannot have a MAGMOM pass else: self.assertEqual(incar[p], ref_incar[p]) # Check SCAN INCAR ref_incar = Incar.from_file( os.path.join(reference_dir, "SCAN_structure_optimization_LiF_vdw/inputs", "INCAR")) incar = Incar.from_file( os.path.join(self._get_launch_dir()[1], "INCAR.gz")) for p in incar.keys(): if p == "KSPACING": self.assertEqual(incar[p], 0.44) elif p == "SIGMA": self.assertEqual(incar[p], 0.05) elif p == "ICHARG": self.assertEqual(incar[p], 1) else: self.assertEqual(incar[p], ref_incar[p]) # get a fw that can be used to identify the workflow fw_id = list(fw_ids.values())[0] # check workflow finished without error wf = self.lp.get_wf_by_fw_id(fw_id) is_completed = [s == "COMPLETED" for s in wf.fw_states.values()] self.assertTrue(all(is_completed))
def wf_bulk_modulus(structure, c=None): """ Bulk modulus workflow from the given structure and config dict. Args: structure (Structure): input structure c (dict): workflow config dict Returns: Workflow """ c = c or {} eos = c.get("EOS", "vinet") vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) user_kpoints_settings = {"grid_density": 7000} # 6 deformations deformations = [(np.identity(3) * (1 + x)).tolist() for x in np.linspace(-0.05, 0.05, 6)] tag = "bulk_modulus group: >>{}<<".format(str(uuid4())) # input set for structure optimization vis_relax = MPRelaxSet(structure, force_gamma=True) v = vis_relax.as_dict() v.update({"user_kpoints_settings": user_kpoints_settings}) vis_relax = vis_relax.__class__.from_dict(v) # static input set for the transmute firework uis_static = {"ISIF": 2, "ISTART": 1, "IBRION": 2, "NSW": 99} # optimization only workflow wf = get_wf(structure, "optimize_only.yaml", params=[{ "vasp_cmd": vasp_cmd, "db_file": db_file, "name": "{} structure optimization".format(tag) }], vis=vis_relax) vis_static = MPStaticSet(structure, force_gamma=True, lepsilon=False, user_kpoints_settings=user_kpoints_settings, user_incar_settings=uis_static) # get the deformations wflow for bulk modulus calculation wf_bm = get_wf_bulk_modulus(structure, eos=eos, user_kpoints_settings=user_kpoints_settings, deformations=deformations, vasp_cmd=vasp_cmd, db_file=db_file, tag=tag, vasp_input_set=vis_static) # chain it wf.append_wf(wf_bm, wf.leaf_fw_ids) wf = add_modify_incar( wf, modify_incar_params={"incar_update": { "ENCUT": 600, "EDIFF": 1e-6 }}) wf = add_common_powerups(wf, c) if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) return wf