def get_relax_static_wf(structures, vasp_cmd=">>vasp_cmd<<", db_file=">>db_file<<", name="regular_relax", **kwargs): """ :param structures: :param vasp_cmd: :param db_file: :param name: :param kwargs: :return: """ wfs = [] for s in structures: fw1 = OptimizeFW(s, vasp_cmd=vasp_cmd, db_file=db_file, parents=[], **kwargs) fw2 = StaticFW(s, vasp_cmd=vasp_cmd, db_file=db_file, parents=[fw1]) wfs.append( Workflow([fw1, fw2], name=name + str(s.composition.reduced_formula))) return wfs
def get_wf_structure_sampler(xdatcar_file, n=10, steps_skip_first=1000, vasp_cmd=">>vasp_cmd<<", db_file=">>db_file<<", name="structure_sampler", **kwargs): """ :param xdatcar_file: :param n: :param steps_skip_first: :param vasp_cmd: :param db_file: :param name: :param kwargs: :return: """ structures = get_sample_structures(xdatcar_path=xdatcar_file, n=n, steps_skip_first=steps_skip_first) wfs = [] for s in structures: fw1 = OptimizeFW(s, vasp_cmd=vasp_cmd, db_file=db_file, parents=[], **kwargs) fw2 = StaticFW(s, vasp_cmd=vasp_cmd, db_file=db_file, parents=[fw1]) wfs.append( Workflow([fw1, fw2], name=name + str(s.composition.reduced_formula))) return wfs
def run_task(self, fw_spec): #create structure from CONTCAR struct = Poscar.from_file('CONTCAR').structure #repeat layers of bulk to create supercell struct.make_supercell([1, 1, self.get("num_layers", 2)]) #add vacuum to create slab struct = add_vacuum(struct, self.get("vacuum", 15)) #add selective dynamics selective_dynamics = [] """ min_bulk = self.get("surf_layers_to_relax",3)/(self.get("atomic_thickness")*self.get("num_layers",2)) * max([site.z for site in struct.sites]) max_bulk = (self.get("atomic_thickness")*self.get("num_layers",2) - self.get("surf_layers_to_relax",3))/(self.get("atomic_thickness")*self.get("num_layers",2)) * max([site.z for site in struct.sites]) for site in struct.sites: if site.z > min_bulk and site.z <= max_bulk: selective_dynamics.append([False, False, False]) else: selective_dynamics.append([True, True, True]) struct.add_site_property("selective_dynamics", selective_dynamics) """ #create optimize and static fireworks using the newly created slab slab_optimize = OptimizeFW(struct, name=name + '_slab_optimization' + time, vasp_cmd=">>vasp_cmd<<", db_file=">>db_file<<", parents=[bulk_optimize]) slab_optimize = Workflow(slab_optimize) optimize_incar_settings = {"ISIF": 2} optimize_update = {"incar_update": optimize_incar_settings} slab_optimize = add_modify_incar(slab_optimize, modify_incar_params=optimize_update, fw_name_constraint='optimization') slab_static = StaticFW(struct, name=name + '_slab_static_' + time, parents=[slab_optimize], prev_calc_loc=True, vasp_cmd=">>vasp_cmd<<", db_file=">>db_file<<") #slab_static.tasks.append(Slab_energy_and_SA()) #surface_energy_calc_fw = Firework(Surface_energy_calc(), parents = [bulk_static, slab_static]) #return FWAction(additions = [slab_optimize, slab_static, surface_energy_calc_fw]) return FWAction(additions=[slab_optimize, slab_static])
def testLobsterFW(self): static_fw = StaticFW(structure=self.structure).name self.assertEqual( LobsterFW(structure=self.structure, parents=static_fw).name, "Si-lobster_calculation", ) lobster_fw = LobsterFW(prev_calc_dir="/", delete_wavecar=True, delete_wavecar_previous_fw=True) self.assertEqual(lobster_fw.name, "unknown-lobster_calculation") self.assertEqual(lobster_fw.tasks[0]["calc_dir"], "/") self.assertEqual(len(lobster_fw.tasks), 7) lobster_fw = LobsterFW(prev_calc_dir="/", delete_wavecar=False, delete_wavecar_previous_fw=False) self.assertEqual(len(lobster_fw.tasks), 5) # check for ValueError when no parent or calc_dir are provided with self.assertRaises(ValueError): LobsterFW()
def run_task(self, fw_spec): inserted_structure = fw_spec.get("optimal_structure") working_ion = fw_spec.get("working_ion") vasptodb_kwargs = fw_spec.get("vasptodb_kwargs") staticfw_kwargs = fw_spec.get("staticfw_kwargs", {}) fw1 = StaticFW( inserted_structure, vasptodb_kwargs=vasptodb_kwargs, db_file=DB_FILE, **staticfw_kwargs, ) n_ion = int( inserted_structure.composition.element_composition[working_ion]) fw2 = Firework( [AnalyzeChgcar(), GetInsertionCalcs()], name=f"Charge Density Analysis-{n_ion}", parents=fw1, ) wf = Workflow([fw1, fw2], name=f"Obtain inserted sites-{n_ion}") wf = get_powerup_wf(wf, fw_spec) update_wf_keys(wf, fw_spec) return FWAction(additions=[wf])
def get_wf(self, scan=False, perform_bader=True, num_orderings_hard_limit=16, c=None): """ Retrieve the FireWorks workflow. Args: scan (bool): if True, use the SCAN functional instead of GGA+U, since the SCAN functional has shown to have improved performance for magnetic systems in some cases perform_bader (bool): if True, make sure the "bader" binary is in your path, will use Bader analysis to calculate atom-projected magnetic moments num_orderings_hard_limit (int): will make sure total number of magnetic orderings does not exceed this number even if there are extra orderings of equivalent symmetry c (dict): additional config dict (as used elsewhere in atomate) Returns: FireWorks Workflow """ c_defaults = {"VASP_CMD": VASP_CMD, "DB_FILE": DB_FILE} additional_fields = {"relax": not self.static} c = c or {} for k, v in c_defaults.items(): if k not in c: c[k] = v fws = [] analysis_parents = [] # trim total number of orderings (useful in high-throughput context) # this is somewhat course, better to reduce num_orderings kwarg and/or # change enumeration strategies ordered_structures = self.ordered_structures ordered_structure_origins = self.ordered_structure_origins def _add_metadata(structure): """ For book-keeping, store useful metadata with the Structure object for later database ingestion including workflow version and a UUID for easier querying of all tasks generated from the workflow. Args: structure: Structure Returns: TransformedStructure """ # this could be further improved by storing full transformation # history, but would require an improved transformation pipeline return TransformedStructure( structure, other_parameters={"wf_meta": self.wf_meta}) ordered_structures = [ _add_metadata(struct) for struct in ordered_structures ] if (num_orderings_hard_limit and len(self.ordered_structures) > num_orderings_hard_limit): ordered_structures = self.ordered_structures[ 0:num_orderings_hard_limit] ordered_structure_origins = self.ordered_structure_origins[ 0:num_orderings_hard_limit] logger.warning("Number of ordered structures exceeds hard limit, " "removing last {} structures.".format( len(self.ordered_structures) - len(ordered_structures))) # always make sure input structure is included if self.input_index and self.input_index > num_orderings_hard_limit: ordered_structures.append( self.ordered_structures[self.input_index]) ordered_structure_origins.append( self.ordered_structure_origins[self.input_index]) # default incar settings user_incar_settings = {"ISYM": 0, "LASPH": True, "EDIFFG": -0.05} if scan: # currently, using SCAN relaxation as a static calculation also # since it is typically high quality enough, but want to make # sure we are also writing the AECCAR* files user_incar_settings.update({"LAECHG": True}) user_incar_settings.update(c.get("user_incar_settings", {})) c["user_incar_settings"] = user_incar_settings for idx, ordered_structure in enumerate(ordered_structures): analyzer = CollinearMagneticStructureAnalyzer(ordered_structure) name = f" ordering {idx} {analyzer.ordering.value} -" if not scan: vis = MPRelaxSet(ordered_structure, user_incar_settings=user_incar_settings) if not self.static: # relax fws.append( OptimizeFW( ordered_structure, vasp_input_set=vis, vasp_cmd=c["VASP_CMD"], db_file=c["DB_FILE"], max_force_threshold=0.05, half_kpts_first_relax=False, name=name + " optimize", )) # static fws.append( StaticFW( ordered_structure, vasp_cmd=c["VASP_CMD"], db_file=c["DB_FILE"], name=name + " static", prev_calc_loc=True, parents=fws[-1], vasptodb_kwargs={ "parse_chgcar": True, "parse_aeccar": True }, )) if not self.static: # so a failed optimize doesn't crash workflow fws[-1].spec["_allow_fizzled_parents"] = True elif scan: # wf_scan_opt is just a single FireWork so can append it directly scan_fws = wf_scan_opt(ordered_structure, c=c).fws # change name for consistency with non-SCAN new_name = scan_fws[0].name.replace("structure optimization", name + " optimize") scan_fws[0].name = new_name scan_fws[0].tasks[-1]["additional_fields"][ "task_label"] = new_name fws += scan_fws analysis_parents.append(fws[-1]) fw_analysis = Firework( MagneticOrderingsToDb( db_file=c["DB_FILE"], wf_uuid=self.uuid, parent_structure=self.sanitized_structure, origins=ordered_structure_origins, input_index=self.input_index, perform_bader=perform_bader, scan=scan, additional_fields=additional_fields, ), name="Magnetic Orderings Analysis", parents=analysis_parents, spec={"_allow_fizzled_parents": True}, ) fws.append(fw_analysis) formula = self.sanitized_structure.composition.reduced_formula wf_name = f"{formula} - magnetic orderings" if scan: wf_name += " - SCAN" wf = Workflow(fws, name=wf_name) wf = add_additional_fields_to_taskdocs(wf, {"wf_meta": self.wf_meta}) tag = f"magnetic_orderings group: >>{self.uuid}<<" wf = add_tags(wf, [tag, ordered_structure_origins]) 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
tilt_count = 15 temp_structs = copy.deepcopy(tilts_and_orders) comp_tag = composition[0] + composition[1] + 'N' + 'O' + str( composition[2]) struct_tag = 'tetra' for structure in temp_structs: if composition[2] == 1: structure.replace_species({'O': 'N', 'N': 'O'}) structure.replace_species({ default_B: composition[1] }) #this will break if B-site is default_a but that shouldn't happen structure.replace_species({default_A: composition[0]}) poscar_key = tetra_dict[tilt_count] opt = OptimizeFW(structure, vasp_cmd='ibrun tacc_affinity vasp_std') stat = StaticFW(parents=opt, vasp_cmd='ibrun tacc_affinity vasp_std') wf = Workflow([opt, stat]) wf = add_modify_incar(wf, modify_incar_params={ 'incar_update': { 'KPAR': 2, 'NCORE': 4, 'NSIM': 8, 'EDIFF': 0.000002, 'LMAXMIX': 6, 'LSCALAPACK': '.FALSE.', 'ALGO': 'All' } }) wf = add_modify_incar(wf, modify_incar_params={