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 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 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 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_raman_spectra(structure, c=None): """ Raman spectra workflow from the given structure and config dict Args: structure (Structure): input structure c (dict): workflow config dict Returns: Workflow """ c = c or {} modes = c.get("MODES", None) step_size = c.get("STEP_SIZE", 0.005) vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) wf = get_wf_raman_spectra(structure, modes=modes, step_size=step_size, vasp_cmd=vasp_cmd, db_file=db_file) wf = add_modify_incar(wf, modify_incar_params={"incar_update": {"ENCUT": 600, "EDIFF": 1e-6}}, fw_name_constraint="static dielectric") 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 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 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_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) user_kpoints_settings = c.get("user_kpoints_settings", {"grid_density": 7000}) deformations = c.get("deformations", [(np.identity(3)*(1+x)).tolist() for x in np.linspace(-0.1, 0.1, 10)]) pressure = c.get("pressure", 0.0) wf = 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) 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_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_bandstructure2D(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) vdw_kernel = c.get("VDW_KERNEL_DIR", VDW_KERNEL_DIR) incar = _read_user_incar('Relax2D.txt') print(incar) mpr2d = MPRelaxSet(structure, force_gamma=True, user_incar_settings=incar) mpr2dstatic = MPRelaxSet(structure, force_gamma=True, user_incar_settings={ "NEDOS": "3001", "EMIN": "-15.0", "EMAX": "15.0" }) #fws = [OptimizeFW2D(structure=structure, vasp_input_set=mpr2d, vasp_cmd=vasp_cmd, db_file=db_file, vdw_kernel_dir=vdw_kernel)] fws = [ OptimizeFW2D(structure=structure, vasp_input_set=mpr2d, vasp_cmd=vasp_cmd, vdw_kernel_dir=vdw_kernel) ] fws.append(StaticFW2D(parents=fws[0], vasp_input_set=mpr2dstatic)) #fws.append(NonSCFFW2D(parents=fws[1], mode='uniform')) fws.append(NonSCFFW2D(parents=fws[1], mode='line')) wf = Workflow(fws) '''check bandstructure.yaml''' ''' wf = get_wf(structure, "bandstructure.yaml", vis=MPScanRelaxSet2D(structure, force_gamma=True,), \ params=[{'vasp_input_set': mpr2d},{},{},{}], common_params={"vasp_cmd": vasp_cmd, "db_file": db_file,}) #"vdw_kernel_dir": vdw_kernel}) ''' 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) wf.name = "{}:{}".format(structure.composition.reduced_formula, "bandStructure") ''' fws = wf.fws fws[0] = new_firework print(fws) ''' return wf
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 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_elastic_constant_minimal(structure, c=None, order=2, sym_reduce=True): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) stencil = np.arange(0.01, 0.01 * order, step=0.01) wf = get_wf_elastic_constant(structure, vasp_cmd=vasp_cmd, db_file=db_file, sym_reduce=sym_reduce, stencils=stencil, order=order, copy_vasp_outputs=False) 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_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_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 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_piezoelectric_constant(structure, c=None): c = c or {} wf = wf_dielectric_constant(structure, c) wf = add_modify_incar(wf, modify_incar_params={"incar_update": {"ENCUT": 1000, "ADDGRID": True, "LREAL": False, "EDIFF": 1e-7} }, fw_name_constraint="static dielectric") for fw in wf.fws: fw.name = fw.name.replace("dielectric", "piezoelectric") 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 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 wf_elastic_constant(structure, c=None): c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) user_kpoints_settings = c.get("user_kpoints_settings", {"grid_density": 7000}) norm_deformations = c.get("norm_deformations", [-0.01, -0.005, 0.005, 0.01]) shear_deformations = c.get("shear_deformations", [-0.06, -0.03, 0.03, 0.06]) wf = get_wf_elastic_constant(structure, vasp_cmd=vasp_cmd, norm_deformations=norm_deformations, shear_deformations=shear_deformations, db_file=db_file, user_kpoints_settings=user_kpoints_settings) mip = {"incar_update":{"ENCUT": 700, "EDIFF": 1e-6, "LAECHG":False}} wf = add_modify_incar(wf, modify_incar_params=mip) 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): 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 wf_raman_spectra(structure, c=None): """ Raman spectra workflow from the given structure and config dict Args: structure (Structure): input structure c (dict): workflow config dict Returns: Workflow """ c = c or {} wf = get_wf_raman_spectra(structure, modes=c.get("modes", None), step_size=c.get("step_size", 0.005), vasp_cmd=c.get("vasp_cmd", "vasp"), db_file=c.get("db_file", None)) wf = add_modify_incar(wf, modify_incar_params={"incar_update": {"ENCUT": 600, "EDIFF": 1e-6}}, fw_name_constraint="static dielectric") if c.get("ADD_WF_METADATA", ADD_WF_METADATA): wf = add_wf_metadata(wf, structure) 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 get_wf_hubbard_hund_linresp(structure, user_incar_settings=None, relax_nonmagnetic=True, spin_polarized=True, applied_potential_range=(-0.2, 0.2), num_evals=9, site_indices_perturb=None, species_perturb=None, find_nearest_sites=True, parallel_scheme=0, ediff_tight=None, c=None): """ Compute Hubbard U (and Hund J) on-site interaction values using GGA+U linear response method proposed by Cococcioni et. al. (DOI: 10.1103/PhysRevB.71.035105) and the spin-polarized response formalism developed by Linscott et. al. (DOI: 10.1103/PhysRevB.98.235157) This workflow relies on the constrained on-site potential functional implemented in VASP, with a helpful tutorial found here: https://www.vasp.at/wiki/index.php/Calculate_U_for_LSDA%2BU Args: structure: user_incar_settings: user INCAR settings relax_nonmagnetic: Restart magnetic SCF runs from non-magnetic calculation, using WAVECAR spin_polarized: Perform spin-dependent perturbations applied_potential_range: Bounds of applied potential num_evals: Number of perturbation evalutaions site_indices_perturb: (must specify if species_perturb=None) List of site indices within Structure indicating perturbation sites; species_perturb: (must specify if site_indices_perturb=None) List of names of species (string) of sites to perturb; First site of that species is selected in the structure find_nearest_sites: If set to true and species_perturb != None, the closest sites (by the Structure distance matrix) will be selected in the response analysis to account for inter-site screening effects parallel_scheme: 0 - (default) self-consistent (SCF) runs use WAVECAR from non-self consistent (NSCF) run at same applied potential; 1 - SCF runs use WAVECAR from ground-state (V=0) run. While reusing the WAVECAR from NSCF run in SCF run may be more efficient (parallel_scheme: 0), the user may also choose to remove the dependency between NSCF and SCF runs (parallel_scheme: 1) ediff_tight: Final energy convergence tolerance, if restarting from a previous run (if not specified, will default to pymatgen default EDIFF) c: Workflow config dict, in the same format as in presets/core.py and elsewhere in atomate Returns: Workflow """ if not structure.is_ordered: raise ValueError( "Please obtain an ordered approximation of the input structure.") if not site_indices_perturb: site_indices_perturb = [] if species_perturb: if find_nearest_sites: site_indices_perturb = find_closest_sites(structure, species_perturb) else: for specie_u in species_perturb: found_specie = False for s in range(len(structure)): site = structure[s] if (Element(str(site.specie)) == Element(specie_u)) \ and (s not in site_indices_perturb): found_specie = True break if not found_specie: raise ValueError("Could not find specie(s) in structure.") site_indices_perturb.append(s) elif not site_indices_perturb: logger.warning("Sites for computing U value are not specified. " "Computing U for first site in structure. ") site_indices_perturb = list(tuple(site_indices_perturb)) num_perturb = len(site_indices_perturb) sites_perturb = [] for site_index_perturb in site_indices_perturb: site = structure[site_index_perturb] sites_perturb.append(site) structure.remove_sites(indices=site_indices_perturb) for site in sites_perturb: structure.insert(i=0, species=site.specie, coords=site.frac_coords, properties=site.properties) # 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 # Calculate groundstate # set user_incar_settings if not user_incar_settings: user_incar_settings = {} # setup VASP input sets uis_gs, uis_ldau, val_dict, vis_ldau = init_linresp_input_sets( user_incar_settings, structure, num_perturb) fws = [] index_fw_gs = [0] ediff_default = vis_ldau.incar['EDIFF'] if not ediff_tight: ediff_tight = 0.1 * ediff_default append_linresp_ground_state_fws(fws, structure, num_perturb, index_fw_gs, uis_gs, relax_nonmagnetic, ediff_default, ediff_tight) # generate list of applied on-site potentials in linear response applied_potential_value_list = [] for counter_perturb in range(num_perturb): applied_potential_values = np.linspace(applied_potential_range[0], applied_potential_range[1], num_evals) applied_potential_values = np.around(applied_potential_values, decimals=9) if 0.0 in applied_potential_values: applied_potential_values = list(applied_potential_values) applied_potential_values.pop(applied_potential_values.index(0.0)) applied_potential_values = np.array(applied_potential_values) applied_potential_value_list.append(applied_potential_values.copy()) for counter_perturb in range(num_perturb): applied_potential_values = applied_potential_value_list[ counter_perturb] for v in applied_potential_values: append_linresp_perturb_fws(v, fws, structure, counter_perturb, num_perturb, index_fw_gs, uis_ldau, val_dict, spin_polarized, relax_nonmagnetic, ediff_default, ediff_tight, parallel_scheme) wf = Workflow(fws) fw_analysis = Firework( HubbardHundLinRespToDb(num_perturb=num_perturb, spin_polarized=spin_polarized, relax_nonmagnetic=relax_nonmagnetic, db_file=DB_FILE, wf_uuid=uuid), name="HubbardHundLinRespToDb", ) 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": "hubbard_hund_linresp", "wf_version": __hubbard_hund_linresp_wf_version__, } }, ) return wf
def wf_gibbs_free_energy(structure, c=None): """The same as workflow Gibbs free energy preset in atomate proper, but allows for choosing between standard and robust optimization with the ``ROBUST`` boolean (default: False) in the config dict. Also uses a much more reasonable 7 deformations with +/- 10% volume Parameters ---------- structure : Structure input structure c : dict workflow config dict Returns ------- Workflow """ c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) robust_optimization = c.get("ROBUST", False) optimize = c.get("OPTIMIZE", False) eos = c.get("EOS", "vinet") qha_type = c.get("QHA_TYPE", "debye_model") # min and max temp in K, default setting is to compute the properties at 300K only t_min = c.get("T_MIN", 300.0) t_max = c.get("T_MAX", 300.0) t_step = c.get("T_STEP", 100.0) pressure = c.get("PRESSURE", 0.0) poisson = c.get("POISSON", 0.25) e_diff = c.get("EDIFF", 1e-6) anharmonic_contribution = c.get("ANHARMONIC_CONTRIBUTION", False) metadata = c.get("METADATA", {}) # 7 deformed structures: from -10% to +10% volume defos = [(np.identity(3) * (1 + x)**(1.0 / 3.0)).tolist() for x in np.linspace(-0.1, 0.1, 7)] deformations = c.get("DEFORMATIONS", defos) user_kpoints_settings = {"grid_density": 7000} tag = "gibbs group: >>{}<<".format(str(uuid4())) # static input set for the transmute firework uis_static = { "ISIF": 2, "ISTART": 1, } lepsilon = False if qha_type not in ["debye_model"]: lepsilon = True try: from phonopy import Phonopy except ImportError: raise RuntimeError( "'phonopy' package is NOT installed but is required for the final " "analysis step; you can alternatively switch to the qha_type to " "'debye_model' which does not require 'phonopy'.") vis_static = PRLStaticSet(structure, force_gamma=True, lepsilon=lepsilon, user_kpoints_settings=user_kpoints_settings, user_incar_settings=uis_static) # get gibbs workflow and chain it to the optimization workflow wf_gibbs = get_wf_gibbs_free_energy( structure, user_kpoints_settings=user_kpoints_settings, deformations=deformations, vasp_cmd=vasp_cmd, db_file=db_file, eos=eos, qha_type=qha_type, pressure=pressure, poisson=poisson, t_min=t_min, t_max=t_max, t_step=t_step, metadata=metadata, anharmonic_contribution=anharmonic_contribution, tag=tag, vasp_input_set=vis_static) # chaining if optimize: # input set for structure optimization vis_relax = PRLRelaxSet(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) name = "{} structure optimization".format(tag) if robust_optimization: wf = get_wf_robust_optimization(structure, vasp_cmd=vasp_cmd, db_file=db_file, name=name, vasp_input_set=vis_relax) else: # optimization only workflow wf = get_wf_optimization(structure, vasp_cmd=vasp_cmd, db_file=db_file, name=name, vasp_input_set=vis_relax) wf.append_wf(wf_gibbs, wf.leaf_fw_ids) else: wf = wf_gibbs wf = add_modify_incar(wf, modify_incar_params={ "incar_update": { "EDIFF": e_diff, "LAECHG": False } }) 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_add_wf_metadata(self): my_wf = self._copy_wf(self.bs_wf) my_wf = add_wf_metadata(my_wf, PymatgenTest.get_structure("Si")) self.assertEqual(my_wf.metadata["nelements"], 1) self.assertEqual(my_wf.metadata["formula"], "Si2")
def wf_vasp2trace_magnetic(structure, c=None): """ Fireworks workflow for running a vasp2trace calculation on a magnetic material. Args: structure (Structure): Pymatgen structure object with magmom site property. Returns: Workflow """ c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) ncoords = 3 * len(structure.sites) if "magmom" in structure.site_properties: magmoms = structure.site_properties["magmom"] magmoms = [str(m) for m in magmoms] magmoms = " ".join(magmoms) nbands = 0 for site in structure.sites: nbands += site.species.total_electrons trim_kpoints = Kpoints( comment="TRIM Points", num_kpts=8, style=Kpoints.supported_modes.Reciprocal, kpts=( (0, 0, 0), (0.5, 0, 0), (0, 0.5, 0), (0, 0, 0.5), (0.5, 0.5, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0.5), ), kpts_shift=(0, 0, 0), kpts_weights=[1, 1, 1, 1, 1, 1, 1, 1], coord_type="Reciprocal", labels=["gamma", "x", "y", "z", "s", "t", "u", "r"], tet_number=0, tet_weight=0, tet_connections=None, ) wf_path = os.path.join(os.path.dirname(__file__), "vasp2trace_magnetic.yaml") wf = get_wf( structure, wf_path, params=[ {}, {}, { "input_set_overrides": { "other_params": {"user_kpoints_settings": trim_kpoints} } }, {}, ], vis=MPStaticSet(structure, potcar_functional="PBE_54", force_gamma=True), common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}, ) dim_data = StructureDimensionality(structure) if np.any( [ dim == 2 for dim in [dim_data.larsen_dim, dim_data.cheon_dim, dim_data.gorai_dim] ] ): wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"IVDW": 11, "EDIFFG": 0.005, "IBRION": 2, "NSW": 100} }, fw_name_constraint="structure optimization", ) else: wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"EDIFFG": 0.005, "IBRION": 2, "NSW": 100} }, fw_name_constraint="structure optimization", ) wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"ADDGRID": ".TRUE.", "LASPH": ".TRUE.", "GGA": "PS"} }, ) # Include magmoms in every calculation wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"ISYM": 2, "MAGMOM": "%s" % magmoms, "ISPIN": 2} }, ) # Spin-polarized band structure wf = add_modify_incar( wf, modify_incar_params={ "incar_update": { "ISYM": 2, "LSORBIT": ".FALSE.", "MAGMOM": "%s" % magmoms, "ISPIN": 2, "LWAVE": ".TRUE.", "NBANDS": nbands, } }, fw_name_constraint="nscf", ) wf = add_common_powerups(wf, c) 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_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
def wf_gibbs_free_energy(structure, c=None): """ Gibbs free energy workflow from the given structure and config dict. Args: structure (Structure): input structure c (dict): workflow config dict Returns: Workflow """ c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) eos = c.get("EOS", "vinet") qha_type = c.get("QHA_TYPE", "debye_model") # min and max temp in K, default setting is to compute the properties at 300K only t_min = c.get("T_MIN", 300.0) t_max = c.get("T_MAX", 300.0) t_step = c.get("T_STEP", 100.0) pressure = c.get("PRESSURE", 0.0) poisson = c.get("POISSON", 0.25) anharmonic_contribution = c.get("ANHARMONIC_CONTRIBUTION", False) metadata = c.get("METADATA", None) # 21 deformed structures: from -10% to +10% defos = [(np.identity(3) * (1 + x)).tolist() for x in np.linspace(-0.1, 0.1, 21)] deformations = c.get("DEFORMATIONS", defos) user_kpoints_settings = {"grid_density": 7000} tag = "gibbs 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) # static input set for the transmute firework uis_static = { "ISIF": 2, "ISTART": 1, } lepsilon = False if qha_type not in ["debye_model"]: lepsilon = True try: from phonopy import Phonopy except ImportError: raise RuntimeError( "'phonopy' package is NOT installed but is required for the final " "analysis step; you can alternatively switch to the qha_type to " "'debye_model' which does not require 'phonopy'.") vis_static = MPStaticSet(structure, force_gamma=True, lepsilon=lepsilon, user_kpoints_settings=user_kpoints_settings, user_incar_settings=uis_static) # get gibbs workflow and chain it to the optimization workflow wf_gibbs = get_wf_gibbs_free_energy( structure, user_kpoints_settings=user_kpoints_settings, deformations=deformations, vasp_cmd=vasp_cmd, db_file=db_file, eos=eos, qha_type=qha_type, pressure=pressure, poisson=poisson, t_min=t_min, t_max=t_max, t_step=t_step, metadata=metadata, anharmonic_contribution=anharmonic_contribution, tag=tag, vasp_input_set=vis_static) # chaining wf.append_wf(wf_gibbs, wf.leaf_fw_ids) wf = add_modify_incar(wf, modify_incar_params={ "incar_update": { "ENCUT": 600, "EDIFF": 1e-6, "LAECHG": False } }) 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_irvsp(structure, magnetic=False, soc=False, v2t=False, c=None): """ Fireworks workflow for running an irvsp calculation. Optionally performs a vasp2trace calculation. Args: structure (Structure): Pymatgen structure object magnetic (bool): Whether the calculation is on a magnetic structure soc (bool): Spin-orbit coupling included v2t (bool): Do a vasp2trace calculation in addition to irvsp. Returns: Workflow """ c = c or {} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) uuid = str(uuid4()) wf_meta = {"wf_uuid": uuid, "wf_name": "Irvsp WF"} magmoms = None if magnetic and "magmom" in structure.site_properties: magmoms_orig = structure.site_properties["magmom"] magmoms = [str(m) for m in magmoms_orig] magmoms = " ".join(magmoms) elif magnetic: raise RuntimeError( "Structure must have magnetic moments in site_properties for magnetic calcualtion!" ) ncoords = 3 * len(structure.sites) nbands = 0 for site in structure.sites: nbands += site.species.total_electrons trim_kpoints = Kpoints( comment="TRIM Points", num_kpts=8, style=Kpoints.supported_modes.Reciprocal, kpts=( (0, 0, 0), (0.5, 0, 0), (0, 0.5, 0), (0, 0, 0.5), (0.5, 0.5, 0), (0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0.5), ), kpts_shift=(0, 0, 0), kpts_weights=[1, 1, 1, 1, 1, 1, 1, 1], coord_type="Reciprocal", labels=["gamma", "x", "y", "z", "s", "t", "u", "r"], tet_number=0, tet_weight=0, tet_connections=None, ) # params dicts for wf params = [ {}, # optimization {}, # standardization {}, # static { "input_set_overrides": { "other_params": {"user_kpoints_settings": trim_kpoints} } }, # nscf {"wf_uuid": uuid}, # irvsp ] if magnetic and v2t: yaml_spec = "irvsp_v2t_magnetic.yaml" params.append({}) elif v2t: yaml_spec = "irvsp_v2t.yaml" params.append({}) else: yaml_spec = "irvsp.yaml" wf = get_wf( structure, yaml_spec, params=params, vis=MPStaticSet(structure, potcar_functional="PBE_54", force_gamma=True), common_params={"vasp_cmd": vasp_cmd, "db_file": db_file}, wf_metadata=wf_meta, ) dim_data = StructureDimensionality(structure) if np.any( [ dim == 2 for dim in [dim_data.larsen_dim, dim_data.cheon_dim, dim_data.gorai_dim] ] ): wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"IVDW": 11, "EDIFFG": 0.005, "IBRION": 2, "NSW": 100} }, fw_name_constraint="structure optimization", ) else: wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"EDIFFG": 0.005, "IBRION": 2, "NSW": 100} }, fw_name_constraint="structure optimization", ) wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"ADDGRID": ".TRUE.", "LASPH": ".TRUE.", "GGA": "PS"} }, ) # Includ ncl magmoms with saxis = (0, 0, 1) if magnetic and soc: magmoms = [] for m in magmoms_orig: magmoms += [0.0, 0.0, m] magmoms = [str(m) for m in magmoms] magmoms = " ".join(magmoms) wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"ISYM": 2, "MAGMOM": "%s" % magmoms} }, ) if magnetic and not soc: # Include magmoms in every calculation wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"ISYM": 2, "MAGMOM": "%s" % magmoms, "ISPIN": 2} }, ) wf = add_modify_incar( wf, modify_incar_params={ "incar_update": { "ISYM": 2, "LSORBIT": ".TRUE." if soc else ".FALSE.", "MAGMOM": "%s" % magmoms if magnetic else "%i*0.0" % ncoords, "ISPIN": 2 if magnetic and not soc else 1, "LWAVE": ".TRUE.", # "NBANDS": nbands, } }, fw_name_constraint="nscf", ) wf = add_common_powerups(wf, c) wf = add_additional_fields_to_taskdocs(wf, {"wf_meta": wf_meta}, task_name_constraint="VaspToDb") 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 get_wf(self, c=None): """ Get the workflow. Returns: Workflow """ c = c or {"VASP_CMD": VASP_CMD, "DB_FILE": DB_FILE} vasp_cmd = c.get("VASP_CMD", VASP_CMD) db_file = c.get("DB_FILE", DB_FILE) nsites = len(self.structure.sites) vis = MPRelaxSet(self.structure, potcar_functional="PBE_54", force_gamma=True) opt_fw = OptimizeFW( self.structure, vasp_input_set=vis, vasp_cmd=c["VASP_CMD"], db_file=c["DB_FILE"], ) vis = MPStaticSet(self.structure, potcar_functional="PBE_54", force_gamma=True) static_fw = StaticFW( self.structure, vasp_input_set=vis, vasp_cmd=c["VASP_CMD"], db_file=c["DB_FILE"], parents=[opt_fw], ) # Separate FW for each BZ surface calc # Run Z2Pack on unique TRIM planes in the BZ surfaces = ["kx_0", "kx_1"] equiv_planes = self.get_equiv_planes() # Only run calcs on inequivalent BZ surfaces if self.symmetry_reduction: for add_surface in equiv_planes.keys(): mark = True for surface in surfaces: if surface in equiv_planes[add_surface]: mark = False if mark and add_surface not in surfaces: surfaces.append(add_surface) else: # 4 TRI surfaces define Z2 in 3D surfaces = ["kx_1", "ky_1", "kz_0", "kz_1"] z2pack_fws = [] for surface in surfaces: z2pack_fw = Z2PackFW( parents=[static_fw], structure=self.structure, surface=surface, uuid=self.uuid, name="z2pack", vasp_cmd=c["VASP_CMD"], db_file=c["DB_FILE"], ) z2pack_fws.append(z2pack_fw) analysis_fw = InvariantFW( parents=z2pack_fws, structure=self.structure, symmetry_reduction=self.symmetry_reduction, equiv_planes=equiv_planes, uuid=self.uuid, name="invariant", db_file=c["DB_FILE"], ) fws = [opt_fw, static_fw] + z2pack_fws + [analysis_fw] wf = Workflow(fws) wf = add_additional_fields_to_taskdocs(wf, {"wf_meta": self.wf_meta}) # Add vdW corrections if structure is layered dim_data = StructureDimensionality(self.structure) if np.any( [ dim == 2 for dim in [dim_data.larsen_dim, dim_data.cheon_dim, dim_data.gorai_dim] ] ): wf = add_modify_incar( wf, modify_incar_params={ "incar_update": { "IVDW": 11, "EDIFFG": 0.005, "IBRION": 2, "NSW": 100, } }, fw_name_constraint="structure optimization", ) wf = add_modify_incar( wf, modify_incar_params={"incar_update": {"IVDW": 11}}, fw_name_constraint="static", ) wf = add_modify_incar( wf, modify_incar_params={"incar_update": {"IVDW": 11}}, fw_name_constraint="z2pack", ) else: wf = add_modify_incar( wf, modify_incar_params={ "incar_update": {"EDIFFG": 0.005, "IBRION": 2, "NSW": 100} }, fw_name_constraint="structure optimization", ) # Helpful vasp settings and no parallelization wf = add_modify_incar( wf, modify_incar_params={ "incar_update": { "ADDGRID": ".TRUE.", "LASPH": ".TRUE.", "GGA": "PS", "NCORE": 1, } }, ) # Generate inputs for Z2Pack with a static calc wf = add_modify_incar( wf, modify_incar_params={"incar_update": {"PREC": "Accurate"}}, fw_name_constraint="static", ) wf = add_common_powerups(wf, c) wf.name = "{} {}".format(self.structure.composition.reduced_formula, "Z2Pack") 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, self.structure) tag = "z2pack: {}".format(self.uuid) wf = add_tags(wf, [tag]) return wf