def run_task(self, fw_spec): # unrelaxed cell cell = Structure.from_file('POSCAR') cell.to(filename='str.out', fmt='mcsqs') # relaxed cell cell = Structure.from_file('CONTCAR') cell.to(filename='str_relax.out', fmt='mcsqs') # check the symmetry out = subprocess.run(['checkrelax', '-1'], stdout=subprocess.PIPE) relaxation = float(out.stdout) # we relax too much, add a volume relax and inflection detection WF as a detour if relaxation > self['tolerance']: from dfttk.fworks import OptimizeFW, InflectionDetectionFW from fireworks import Workflow from dfttk.input_sets import RelaxSet from dfttk.utils import add_modify_incar_by_FWname, add_modify_kpoints_by_FWname fws = [] vis = RelaxSet(self.get('structure'), volume_relax=True) vol_relax_fw = OptimizeFW( self.get('structure'), symmetry_tolerance=None, job_type='normal', name='Volume relax', #record_path = True, vasp_input_set=vis, modify_incar={'ISIF': 7}, vasp_cmd=self.get('vasp_cmd'), db_file=self.get('db_file'), metadata=self.get('metadata'), ) fws.append(vol_relax_fw) modify_incar_params = self.get('modify_incar_params') modify_kpoints_params = self.get('modify_kpoints_params') # we have to add the calc locs for this calculation by hand # because the detour action seems to disable spec mods fws.append( InflectionDetectionFW( self.get('structure'), parents=[vol_relax_fw], Pos_Shape_relax=self.get('Pos_Shape_relax') or False, metadata=self.get('metadata'), db_file=self.get('db_file'), spec={ 'calc_locs': extend_calc_locs(self.get('name', 'Full relax'), fw_spec) })) infdet_wf = Workflow(fws) add_modify_incar_by_FWname(infdet_wf, modify_incar_params=modify_incar_params) add_modify_kpoints_by_FWname( infdet_wf, modify_kpoints_params=modify_kpoints_params) return FWAction(detours=[infdet_wf])
def get_wf_gibbs_SQS(structure, num_deformations=7, deformation_fraction=(-0.1, 0.1), phonon=False, phonon_supercell_matrix=None, run_isif2=False, pass_isif4=False, t_min=5, t_max=2000, t_step=5, tolerance=0.01, volume_spacing_min=0.03, vasp_cmd=None, db_file=None, metadata=None, name='EV_QHA', symmetry_tolerance=0.05, passinitrun=False, relax_path='', modify_incar_params={}, modify_kpoints_params={}, verbose=False, store_volumetric_data=False): """ E - V curve workflow Parameters ------ structure: pymatgen.Structure num_deformations: int deformation_fraction: float Can be a float (a single value) or a 2-type of a min,max deformation fraction. Default is (-0.05, 0.1) leading to volumes of 0.95-1.10. A single value gives plus/minus by default. phonon : bool Whether to do a phonon calculation. Defaults to False, meaning the Debye model. phonon_supercell_matrix : list 3x3 array of the supercell matrix, e.g. [[2,0,0],[0,2,0],[0,0,2]]. Must be specified if phonon is specified. t_min : float Minimum temperature t_step : float Temperature step size t_max : float Maximum temperature (inclusive) tolerance: float Acceptable value for average RMS, recommend >= 0.005. volume_spacing_min: float Minimum ratio of Volumes spacing vasp_cmd : str Command to run VASP. If None (the default) is passed, the command will be looked up in the FWorker. db_file : str Points to the database JSON file. If None (the default) is passed, the path will be looked up in the FWorker. name : str Name of the workflow metadata : dict Metadata to include passinitrun : bool Set True to pass initial VASP running if the results exist in DB, use carefully to keep data consistent. relax_path : str Set the path already exists for new static calculations; if set as '', will try to get the path from db_file. modify_incar_params : dict User can use these params to modify the INCAR set. It is a dict of class ModifyIncar with keywords in Workflow name. modify_kpoints_params : dict User can use these params to modify the KPOINTS set. It is a dict of class ModifyKpoints with keywords in Workflow name. Only 'kpts' supported now. run_isif2: bool Whether run isif=2 calculation before isif=4 running, pass to get_gibbs. pass_isif4: bool Whether pass isif=4 calculation, pass to get_gibbs. """ vasp_cmd = vasp_cmd or VASP_CMD db_file = db_file or DB_FILE metadata = metadata or {} tag = metadata.get('tag', '{}'.format(str(uuid4()))) if isinstance(deformation_fraction, (list, tuple)): deformations = np.linspace(1 + deformation_fraction[0], 1 + deformation_fraction[1], num_deformations) vol_spacing = max((deformation_fraction[1] - deformation_fraction[0]) / (num_deformations - 0.999999) + 0.001, volume_spacing_min) else: deformations = np.linspace(1 - deformation_fraction, 1 + deformation_fraction, num_deformations) vol_spacing = max( deformation_fraction / (num_deformations - 0.999999) * 2 + 0.001, volume_spacing_min) if 'tag' not in metadata.keys(): metadata['tag'] = tag relax_path, run_isif2, pass_isif4 = check_relax_path( relax_path, db_file, tag, run_isif2, pass_isif4) fws = [] prestatic_calcs = [] if relax_path != '': pass else: for i, deformation in enumerate(np.linspace(0.85, 1.15, 7)): structure1 = deepcopy(structure) structure1.scale_lattice(deformation * structure.volume) vis_PreStatic = PreStaticSet(structure1) prestatic = StaticFW(structure=structure1, scale_lattice=deformation, name='VR_%.3f-PreStatic' % deformation, prev_calc_loc=False, vasp_input_set=vis_PreStatic, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, Prestatic=True, store_volumetric_data=store_volumetric_data) fws.append(prestatic) prestatic_calcs.append(prestatic) check_result = Firework( PreEV_check(db_file=db_file, tag=tag, relax_path=relax_path, deformations=deformations, structure=structure, tolerance=tolerance, threshold=14, vol_spacing=vol_spacing, vasp_cmd=vasp_cmd, run_isif2=run_isif2, metadata=metadata, t_min=t_min, t_max=t_max, t_step=t_step, phonon=phonon, symmetry_tolerance=symmetry_tolerance, phonon_supercell_matrix=phonon_supercell_matrix, verbose=verbose, pass_isif4=pass_isif4, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params), parents=prestatic_calcs, name='%s-PreEV_check' % structure.composition.reduced_formula) fws.append(check_result) wfname = "{}:{}".format(structure.composition.reduced_formula, name) wf = Workflow(fws, name=wfname, metadata=metadata) add_modify_incar_by_FWname(wf, modify_incar_params=modify_incar_params) add_modify_kpoints_by_FWname(wf, modify_kpoints_params=modify_kpoints_params) return wf
def get_wf_gibbs(structure, num_deformations=7, deformation_fraction=(-0.1, 0.1), run_isif2=False, phonon=False, phonon_supercell_matrix=None, pass_isif4=False, t_min=5, t_max=2000, t_step=5, tolerance=0.01, volume_spacing_min=0.03, vasp_cmd=None, db_file=None, metadata=None, name='EV_QHA', symmetry_tolerance=0.05, passinitrun=False, relax_path='', modify_incar_params={}, modify_kpoints_params={}, verbose=False, store_volumetric_data=False): """ E - V curve workflow Parameters ------ structure: pymatgen.Structure num_deformations: int deformation_fraction: float Can be a float (a single value) or a 2-type of a min,max deformation fraction. Default is (-0.05, 0.1) leading to volumes of 0.95-1.10. A single value gives plus/minus by default. phonon : bool Whether to do a phonon calculation. Defaults to False, meaning the Debye model. phonon_supercell_matrix : list 3x3 array of the supercell matrix, e.g. [[2,0,0],[0,2,0],[0,0,2]]. Must be specified if phonon is specified. t_min : float Minimum temperature t_step : float Temperature step size t_max : float Maximum temperature (inclusive) tolerance: float Acceptable value for average RMS, recommend >= 0.005. volume_spacing_min: float Minimum ratio of Volumes spacing vasp_cmd : str Command to run VASP. If None (the default) is passed, the command will be looked up in the FWorker. db_file : str Points to the database JSON file. If None (the default) is passed, the path will be looked up in the FWorker. name : str Name of the workflow metadata : dict Metadata to include passinitrun : bool Set True to pass initial VASP running if the results exist in DB, use carefully to keep data consistent. relax_path : str Set the path already exists for new static calculations; if set as '', will try to get the path from db_file. modify_incar_params : dict User can use these params to modify the INCAR set. It is a dict of class ModifyIncar with keywords in Workflow name. modify_kpoints_params : dict User can use these params to modify the KPOINTS set. It is a dict of class ModifyKpoints with keywords in Workflow name. Only 'kpts' supported now. run_isif2: bool Whether run isif=2 calculation before isif=4 running. pass_isif4: bool Whether pass isif=4 calculation. """ vasp_cmd = vasp_cmd or VASP_CMD db_file = db_file or DB_FILE if db_file == ">>db_file<<": #In PengGao's version, some function used the absolute db_file from fireworks.fw_config import config_to_dict from monty.serialization import loadfn db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"] site_properties = deepcopy(structure).site_properties metadata = metadata or {} tag = metadata.get('tag', '{}'.format(str(uuid4()))) if isinstance(deformation_fraction, (list, tuple)): deformations = np.linspace(1 + deformation_fraction[0], 1 + deformation_fraction[1], num_deformations) vol_spacing = max((deformation_fraction[1] - deformation_fraction[0]) / (num_deformations - 0.999999) + 0.001, volume_spacing_min) else: deformations = np.linspace(1 - deformation_fraction, 1 + deformation_fraction, num_deformations) vol_spacing = max( deformation_fraction / (num_deformations - 0.999999) * 2 + 0.001, volume_spacing_min) fws = [] if 'tag' not in metadata.keys(): metadata['tag'] = tag relax_path, run_isif2, pass_isif4 = check_relax_path( relax_path, db_file, tag, run_isif2, pass_isif4) if (relax_path == ''): # follow a scheme of # 1. Full relax + symmetry check # 2. If symmetry check fails, detour to 1. Volume relax, 2. inflection detection # 3. Inflection detection # 4. Static EV # 5. Phonon EV # for each FW, we set the structure to the original structure to verify to ourselves that the # volume deformed structure is set by input set. vis_relax = RelaxSet(structure) print('Full relax will be running ...') full_relax_fw = OptimizeFW(structure, symmetry_tolerance=symmetry_tolerance, job_type='normal', name='Full relax', prev_calc_loc=False, vasp_input_set=vis_relax, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, record_path=True, run_isif2=run_isif2, pass_isif4=pass_isif4, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, store_volumetric_data=store_volumetric_data, spec={'_preserve_fworker': True}) fws.append(full_relax_fw) else: full_relax_fw = None check_result = Firework( EVcheck_QHA(db_file=db_file, tag=tag, relax_path=relax_path, deformations=deformations, site_properties=site_properties, tolerance=tolerance, threshold=14, vol_spacing=vol_spacing, vasp_cmd=vasp_cmd, metadata=metadata, t_min=t_min, t_max=t_max, t_step=t_step, phonon=phonon, symmetry_tolerance=symmetry_tolerance, phonon_supercell_matrix=phonon_supercell_matrix, verbose=verbose, run_isif2=run_isif2, pass_isif4=pass_isif4, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, store_volumetric_data=store_volumetric_data), parents=full_relax_fw, name='%s-EVcheck_QHA' % structure.composition.reduced_formula) fws.append(check_result) wfname = "{}:{}".format(structure.composition.reduced_formula, name) wf = Workflow(fws, name=wfname, metadata=metadata) add_modify_incar_by_FWname(wf, modify_incar_params=modify_incar_params) add_modify_kpoints_by_FWname(wf, modify_kpoints_params=modify_kpoints_params) return wf
def get_wf_gibbs_robust(structure, num_deformations=7, deformation_fraction=(-0.1, 0.1), phonon=False, isif4=False, phonon_supercell_matrix=None, override_symmetry_tolerances=None, t_min=5, t_max=2000, t_step=5, eos_tolerance=0.01, volume_spacing_min=0.03, vasp_cmd=None, db_file=None, metadata=None, name='EV_QHA', override_default_vasp_params=None, modify_incar_params={}, modify_kpoints_params={}, verbose=False, level=1, phonon_supercell_matrix_min=60, phonon_supercell_matrix_max=120, optimize_sc=False, force_phonon=False, stable_tor=0.01, store_volumetric_data=False): """ E - V curve workflow Parameters ------ structure: pymatgen.Structure The initial structure num_deformations: int The number of deformation deformation_fraction: float Can be a float (a single value) or a 2-type of a min,max deformation fraction. Default is (-0.1, 0.1) leading to volumes of 0.90-1.10. A single value gives plus/minus by default. phonon : bool Whether to do a phonon calculation. Defaults to False, meaning the Debye model. phonon_supercell_matrix : list/str 3x3 array of the supercell matrix, e.g. [[2,0,0],[0,2,0],[0,0,2]]. Must be specified if phonon is specified. if string, choose from 'atoms', 'lattice' or 'volume' (only the first letter works, case insensitive), which determine who to determin the matrix override_symmetry_tolerances : dict The symmetry tolerance. It contains three keys, default: {'tol_energy':0.025, 'tol_strain':0.05, 'tol_bond':0.1} t_min : float Minimum temperature t_step : float Temperature step size t_max : float Maximum temperature (inclusive) eos_tolerance: float Acceptable value for average RMS, recommend >= 0.005. volume_spacing_min: float Minimum ratio of Volumes spacing vasp_cmd : str Command to run VASP. If None (the default) is passed, the command will be looked up in the FWorker. db_file : str Points to the database JSON file. If None (the default) is passed, the path will be looked up in the FWorker. name : str Name of the workflow metadata : dict Metadata to include override_default_vasp_params: dict Override vasp parameters for all vasp jobs. e.g override_default_vasp_params={'user_incar_settings': {'ISIF': 4}} modify_incar_params : dict Override vasp settings in firework level User can use these params to modify the INCAR set. It is a dict of class ModifyIncar with keywords in Workflow name. modify_kpoints_params : dict User can use these params to modify the KPOINTS set. It is a dict of class ModifyKpoints with keywords in Workflow name. Only 'kpts' supported now. phonon_supercell_matrix_min/max: int minimum/maximum atoms/lattice/volume(controlled by scale_object, default is using atoms) optimize_sc: bool Optimize the super cell matrix (True) or not (False) If False, then use the closest integer transformation matrix of ideal matrix stable_tor: float The tolerance for phonon stability (the percentage of negative part frequency) """ vasp_cmd = vasp_cmd or VASP_CMD db_file = db_file or DB_FILE override_symmetry_tolerances = override_symmetry_tolerances or { 'tol_energy': 0.025, 'tol_strain': 0.05, 'tol_bond': 0.10 } override_default_vasp_params = override_default_vasp_params or {} site_properties = deepcopy(structure).site_properties metadata = metadata or {} tag = metadata.get('tag', '{}'.format(str(uuid4()))) metadata.update({'tag': tag}) deformations = _get_deformations(deformation_fraction, num_deformations) vol_spacing = max( (deformations[-1] - deformations[0]) / (num_deformations - 1), volume_spacing_min) common_kwargs = { 'vasp_cmd': vasp_cmd, 'db_file': ">>db_file<<", "metadata": metadata, "tag": tag, 'override_default_vasp_params': override_default_vasp_params } robust_opt_kwargs = { 'isif': 7, 'isif4': isif4, 'level': level, 'override_symmetry_tolerances': override_symmetry_tolerances } vasp_kwargs = { 'modify_incar_params': modify_incar_params, 'modify_kpoints_params': modify_kpoints_params } t_kwargs = {'t_min': t_min, 't_max': t_max, 't_step': t_step} eos_kwargs = { 'deformations': deformations, 'vol_spacing': vol_spacing, 'eos_tolerance': eos_tolerance, 'threshold': 14 } fws = [] robust_opt_fw = RobustOptimizeFW( structure, prev_calc_loc=False, name='Full relax', store_volumetric_data=store_volumetric_data, **robust_opt_kwargs, **vasp_kwargs, **common_kwargs) fws.append(robust_opt_fw) check_qha_parent = [] if phonon: if isinstance(phonon_supercell_matrix, str): if phonon_supercell_matrix == 'Yphon': phonon_supercell_matrix = supercell_scaling_by_Yphon( structure, supercellsize=phonon_supercell_matrix_max) else: phonon_supercell_matrix = supercell_scaling_by_atom_lat_vol( structure, min_obj=phonon_supercell_matrix_min, max_obj=phonon_supercell_matrix_max, scale_object=phonon_supercell_matrix, target_shape='sc', lower_search_limit=-2, upper_search_limit=2, verbose=verbose, sc_tolerance=1e-5, optimize_sc=optimize_sc) ph_scm_size = np.array(phonon_supercell_matrix).shape if not (ph_scm_size[0] == 3 and ph_scm_size[1] == 3): raise ValueError( 'Current phonon_supercell_matrix({}) is not correct.'.format( phonon_supercell_matrix)) phonon_wf = PhononFW(structure, phonon_supercell_matrix, parents=robust_opt_fw, prev_calc_loc='static', name='structure_{:.3f}-phonon'.format( structure.volume), stable_tor=stable_tor, **t_kwargs, **common_kwargs) fws.append(phonon_wf) check_qha_parent.append(phonon_wf) check_relax_fw = Firework(CheckRelaxScheme(db_file=">>db_file<<", tag=tag), parents=robust_opt_fw, name="{}-CheckRelaxScheme".format( structure.composition.reduced_formula)) fws.append(check_relax_fw) check_qha_parent.append(check_relax_fw) check_qha_fw = Firework( EVcheck_QHA(site_properties=site_properties, verbose=verbose, stable_tor=stable_tor, phonon=phonon, phonon_supercell_matrix=phonon_supercell_matrix, force_phonon=force_phonon, override_symmetry_tolerances=override_symmetry_tolerances, store_volumetric_data=store_volumetric_data, **eos_kwargs, **vasp_kwargs, **t_kwargs, **common_kwargs), parents=check_qha_parent, name='{}-EVcheck_QHA'.format(structure.composition.reduced_formula)) fws.append(check_qha_fw) wfname = "{}:{}".format(structure.composition.reduced_formula, name) wf = Workflow(fws, name=wfname, metadata=metadata) add_modify_incar_by_FWname(wf, modify_incar_params=modify_incar_params) add_modify_kpoints_by_FWname(wf, modify_kpoints_params=modify_kpoints_params) return wf
def run_task(self, fw_spec): ''' run_num: maximum number of appending VASP running; this limitation is to avoid always running due to bad settings; only for internal usage; Important args: tolerance: acceptable value for average RMS, recommend >= 0.005; threshold: total point number above the value should be reduced, recommend < 16 or much time to run; del_limited: maximum deletion ration for large results; vol_spacing: the maximum ratio step between two volumes, larger step will be inserted points to calculate; ''' max_run = 10 deformations = self.get('deformations') or [] db_file = self['db_file'] tag = self['tag'] vasp_cmd = self['vasp_cmd'] metadata = self['metadata'] relax_path = self['relax_path'] or '' structure = self.get('structure') or None run_num = self.get('run_num') or 0 tolerance = self.get('tolerance') or 0.005 threshold = self.get('threshold') or 14 del_limited = self.get('del_limited') or 0.3 vol_spacing = self.get('vol_spacing') or 0.05 t_min = self.get('t_min') or 5 t_max = self.get('t_max') or 2000 t_step = self.get('t_step') or 5 phonon = self.get('phonon') or False phonon_supercell_matrix = self.get('phonon_supercell_matrix') or None verbose = self.get('verbose') or False modify_incar_params = self.get('modify_incar_params') or {} modify_kpoints_params = self.get('modify_kpoints_params') or {} powerups_options = modify_incar_params.get('powerups', None) symmetry_tolerance = self.get('symmetry_tolerance') or None run_isif2 = self.get('run_isif2') or None pass_isif4 = self.get('pass_isif4') or False site_properties = self.get('site_properties') or None store_volumetric_data = self.get('store_volumetric_data', False) run_num += 1 volumes, energies = self.get_orig_EV_structure(db_file, tag) self.check_points(db_file, metadata, tolerance, 0.1, del_limited, volumes, energies, verbose) EVcheck_result = init_evcheck_result(run_num, self.correct, volumes, energies, tolerance, threshold, vol_spacing, self.error, metadata) structure.scale_lattice(self.minE_value) if site_properties: for pkey in site_properties: structure.add_site_property(pkey, site_properties[pkey]) vol_orig = structure.volume volume, energy = gen_volenergdos(self.points, volumes, energies) vol_adds = self.check_vol_coverage(volume, vol_spacing, vol_orig, run_num, energy, structure, phonon, db_file, tag, t_min, t_max, t_step, EVcheck_result) # Normalized to 1 if self.correct or len(vol_adds) > 0: EVcheck_result['sellected'] = volume EVcheck_result['minE_value'] = self.minE_value EVcheck_result['append'] = (vol_adds).tolist() # Marked as adopted in db lpad = LaunchPad.auto_load() fws = [] if len(vol_adds) > 0: # VASP calculations need to append if run_num < max_run: # Do VASP and check again print('Appending PreStatic of : %s to calculate in VASP!' % (vol_adds * vol_orig).tolist()) fws = [] prestatic_calcs = [] vis_prestatic = PreStaticSet(structure) for vol_add in vol_adds: prestatic = StaticFW( structure=structure, job_type='normal', name='VR_%.3f-PreStatic' % vol_add, prev_calc_loc=False, vasp_input_set=vis_prestatic, vasp_cmd=">>vasp_cmd<<", db_file=self.get('db_file', DB_FILE), metadata=metadata, Prestatic=True) fws.append(prestatic) prestatic_calcs.append(prestatic) check_result = Firework( PreEV_check( db_file=self.get('db_file', DB_FILE), tag=tag, relax_path=relax_path, deformations=deformations, run_isif2=run_isif2, tolerance=tolerance, threshold=14, vol_spacing=vol_spacing, vasp_cmd=">>vasp_cmd<<", pass_isif4=pass_isif4, metadata=metadata, t_min=t_min, t_max=t_max, t_step=t_step, phonon=phonon, symmetry_tolerance=symmetry_tolerance, phonon_supercell_matrix=phonon_supercell_matrix, verbose=verbose, site_properties=site_properties, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params), parents=prestatic_calcs, name='%s-PreEV_check%s' % (structure.composition.reduced_formula, run_num)) fws.append(check_result) strname = "{}:{}".format( structure.composition.reduced_formula, 'PreEV_check') wfs = Workflow(fws, name=strname, metadata=metadata) if modify_incar_params != {}: from dfttk.utils import add_modify_incar_by_FWname add_modify_incar_by_FWname( wfs, modify_incar_params=modify_incar_params) if modify_kpoints_params != {}: from dfttk.utils import add_modify_kpoints_by_FWname add_modify_kpoints_by_FWname( wfs, modify_kpoints_params=modify_kpoints_params) wfs = Customizing_Workflows( wfs, powerups_options=powerups_options) lpad.add_wf(wfs) else: too_many_run_error() else: # No need to do more VASP calculation, QHA could be running relax_path, run_isif2, pass_isif4 = check_relax_path( relax_path, db_file, tag, run_isif2, pass_isif4) if relax_path == '': print( 'Success in PreStatic calculations, entering Position relax ...' ) vis_relax = RelaxSet(structure) ps2_relax_fw = OptimizeFW( structure, symmetry_tolerance=symmetry_tolerance, job_type='normal', name='MinE V=%.3f relax' % vol_orig, prev_calc_loc=False, vasp_input_set=vis_relax, vasp_cmd=">>vasp_cmd<<", db_file=self.get('db_file', DB_FILE), metadata=metadata, record_path=True, modify_incar={'ISIF': 2}, run_isif2=run_isif2, pass_isif4=pass_isif4, modify_incar_params=modify_incar_params, modify_kpoints_params=modify_kpoints_params, spec={'_preserve_fworker': True}, store_volumetric_data=store_volumetric_data) fws.append(ps2_relax_fw) else: print( 'Initial setting found, enter static claculations ...') ps2_relax_fw = None check_result = Firework( EVcheck_QHA( db_file=self.get('db_file', DB_FILE), tag=tag, relax_path=relax_path, tolerance=tolerance, run_isif2=run_isif2, threshold=threshold, vol_spacing=vol_spacing, vasp_cmd=">>vasp_cmd<<", run_num=run_num, metadata=metadata, t_min=t_min, t_max=t_max, t_step=t_step, phonon=phonon, deformations=deformations, phonon_supercell_matrix=phonon_supercell_matrix, symmetry_tolerance=symmetry_tolerance, modify_incar_params=modify_incar_params, verbose=verbose, pass_isif4=pass_isif4, modify_kpoints_params=modify_kpoints_params, site_properties=site_properties), parents=ps2_relax_fw, name='%s-EVcheck_QHA' % structure.composition.reduced_formula, store_volumetric_data=store_volumetric_data) fws.append(check_result) strname = "{}:{}".format(structure.composition.reduced_formula, 'prePS2_Relax') wfs = Workflow(fws, name=strname, metadata=metadata) if modify_incar_params != {}: from dfttk.utils import add_modify_incar_by_FWname add_modify_incar_by_FWname( wfs, modify_incar_params=modify_incar_params) if modify_kpoints_params != {}: from dfttk.utils import add_modify_kpoints_by_FWname add_modify_kpoints_by_FWname( wfs, modify_kpoints_params=modify_kpoints_params) wfs = Customizing_Workflows(wfs, powerups_options=powerups_options) lpad.add_wf(wfs) else: # failure to meet the tolerance if len(volumes ) == 0: #self.error == 1e10: # Bad initial running set pass_result_error() else: # fitting fails tol_error() import json with open('PreStatic_check_summary.json', 'w') as fp: json.dump(EVcheck_result, fp)
def run_task(self, fw_spec): ''' run_num: maximum number of appending VASP running; this limitation is to avoid always running due to bad settings; only for internal usage; Important args: eos_tolerance: acceptable value for average RMS, recommend >= 0.005; threshold: total point number above the value should be reduced, recommend < 16 or much time to run; del_limited: maximum deletion ration for large results; vol_spacing: the maximum ratio step between two volumes, larger step will be inserted points to calculate; ''' # Get the parameters from the object max_run = 10 db_file = env_chk(self.get('db_file', DB_FILE), fw_spec) #always concrete db_fiel vasp_cmd = ">>vasp_cmd<<" #chould change for user to provide the change deformations = self.get('deformations', []) run_num = self.get('run_num', 0) eos_tolerance = self.get('eos_tolerance', 0.005) threshold = self.get('threshold', 14) del_limited = self.get('del_limited', 0.3) vol_spacing = self.get('vol_spacing', 0.05) t_min = self.get('t_min', 5) t_max = self.get('t_max', 2000) t_step = self.get('t_step', 5) phonon = self.get('phonon', False) force_phonon = self.get('force_phonon', False) phonon_supercell_matrix = self.get('phonon_supercell_matrix', None) verbose = self.get('verbose', False) modify_kpoints_params = self.get('modify_kpoints_params', {}) site_properties = self.get('site_properties', None) modify_incar_params = self.get('modify_incar_params', {}) powerups_options = modify_incar_params.get('powerups', None) override_default_vasp_params = self.get('override_default_vasp_params', {}) user_incar_settings = override_default_vasp_params.get( 'user_incar_settings', {}) powerups_options = user_incar_settings.get('powerups', powerups_options) override_symmetry_tolerances = self.get('override_symmetry_tolerances', {}) store_volumetric_data = self.get('store_volumetric_data', False) stable_tor = self.get('stable_tor', 0.01) force_phonon = self.get('force_phonon', False) test = self.get('test', False) relax_structure = self.get('structure') or fw_spec.get( 'structure', None) relax_scheme = self.get('relax_scheme') or fw_spec.get( 'relax_scheme', [2]) relax_phonon = fw_spec.get('relax_phonon', False) #Only set phonon=True and ISIF=4 passed, then run phonon if not force_phonon: phonon = phonon and relax_phonon metadata = self.get('metadata', {}) tag = self.get('tag', metadata.get('tag', None)) if tag is None: tag = str(uuid4()) metadata['tag'] = tag common_kwargs = { 'vasp_cmd': vasp_cmd, 'db_file': self.get('db_file', DB_FILE), "metadata": metadata, "tag": tag, 'override_default_vasp_params': override_default_vasp_params, } vasp_kwargs = { 'modify_incar_params': modify_incar_params, 'modify_kpoints_params': modify_kpoints_params } t_kwargs = {'t_min': t_min, 't_max': t_max, 't_step': t_step} eos_kwargs = { 'vol_spacing': vol_spacing, 'eos_tolerance': eos_tolerance, 'threshold': 14 } run_num += 1 #Some initial checks #TODO: add phonon after RobustOptimizeFW if phonon: #To check if the consistent of phonon and optimize if not consistent_check_db(db_file, tag): print('Please check DB, DFTTK running ended!') return if relax_structure is not None: structure = deepcopy(relax_structure) else: raise ValueError( 'Not structure in spec, please provide structure as input') if site_properties: for pkey in site_properties: structure.add_site_property(pkey, site_properties[pkey]) # get original EV curve volumes, energies, dos_objs = self.get_orig_EV(db_file, tag) vol_adds = check_deformations_in_volumes(deformations, volumes, structure.volume) if (len(vol_adds)) == 0: self.check_points(db_file, metadata, eos_tolerance, threshold, del_limited, volumes, energies, verbose) else: self.correct = True self.error = 1e10 EVcheck_result = init_evcheck_result(append_run_num=run_num, correct=self.correct, volumes=volumes, energies=energies, eos_tolerance=eos_tolerance, threshold=threshold, vol_spacing=vol_spacing, error=self.error, metadata=metadata) if self.correct: vol_orig = structure.volume if (len(vol_adds)) == 0: volume, energy, dos_obj = gen_volenergdos( self.points, volumes, energies, dos_objs) vol_adds = self.check_vol_coverage( volume, vol_spacing, vol_orig, run_num, energy, structure, dos_obj, phonon, db_file, tag, t_min, t_max, t_step, EVcheck_result) # Normalized to 1 EVcheck_result['selected'] = volume EVcheck_result['append'] = (vol_adds).tolist() # Marked as adopted in db mark_adopted(tag, db_file, volume, phonon=phonon) lpad = LaunchPad.auto_load() fws = [] if len(vol_adds) > 0: # VASP calculations need to append if run_num < max_run: # Do VASP and check again print( 'Appending the volumes of : %s to calculate in VASP!' % (vol_adds).tolist()) calcs = [] #vis_relax = RelaxSet(structure) #vis_static = StaticSet(structure) #isif2 = 5 if 'infdet' in relax_path else 4 for vol_add in vol_adds: struct = deepcopy(structure) struct.scale_lattice(structure.volume * vol_add) relax_parents_fw = None for isif_i in relax_scheme: #record_path=record_path relax_fw = OptimizeFW( struct, isif=isif_i, store_volumetric_data=store_volumetric_data, name="relax_Vol{:.3f}".format(vol_add), vasp_input_set=None, job_type="normal", override_symmetry_tolerances= override_symmetry_tolerances, prev_calc_loc=True, parents=relax_parents_fw, db_insert=False, force_gamma=True, modify_incar={}, **vasp_kwargs, **common_kwargs) relax_parents_fw = deepcopy(relax_fw) fws.append(relax_fw) calcs.append(relax_fw) static_fw = StaticFW( struct, isif=relax_scheme[-1], name='static_Vol{:.3f}'.format(vol_add), vasp_input_set=None, prev_calc_loc=True, parents=relax_parents_fw, store_volumetric_data=store_volumetric_data, **common_kwargs) fws.append(static_fw) calcs.append(static_fw) if phonon: #visphonon = ForceConstantsSet(struct) phonon_fw = PhononFW( struct, phonon_supercell_matrix, vasp_input_set=None, stable_tor=stable_tor, name='structure_{:.3f}-phonon'.format(vol_add), prev_calc_loc=True, parents=static_fw, **t_kwargs, **common_kwargs) fws.append(phonon_fw) calcs.append(phonon_fw) check_result = Firework( EVcheck_QHA( structure=relax_structure, relax_scheme=relax_scheme, store_volumetric_data=store_volumetric_data, run_num=run_num, verbose=verbose, site_properties=site_properties, stable_tor=stable_tor, phonon=phonon, phonon_supercell_matrix=phonon_supercell_matrix, force_phonon=force_phonon, **eos_kwargs, **vasp_kwargs, **t_kwargs, **common_kwargs), parents=calcs, name='{}-EVcheck_QHA'.format( structure.composition.reduced_formula)) fws.append(check_result) strname = "{}:{}".format( structure.composition.reduced_formula, 'EV_QHA_Append') wfs = Workflow(fws, name=strname, metadata=metadata) if modify_incar_params != {}: from dfttk.utils import add_modify_incar_by_FWname add_modify_incar_by_FWname( wfs, modify_incar_params=modify_incar_params) if modify_kpoints_params != {}: from dfttk.utils import add_modify_kpoints_by_FWname add_modify_kpoints_by_FWname( wfs, modify_kpoints_params=modify_kpoints_params) wfs = Customizing_Workflows( wfs, powerups_options=powerups_options) if not test: lpad.add_wf(wfs) else: too_many_run_error() else: # No need to do more VASP calculation, QHA could be running print('Success in Volumes-Energies checking, enter QHA ...') debye_fw = Firework(QHAAnalysis(phonon=phonon, t_min=t_min, t_max=t_max, t_step=t_step, db_file=self.get( 'db_file', DB_FILE), tag=tag, metadata=metadata), name="{}-qha_analysis".format( structure.composition.reduced_formula)) fws.append(debye_fw) ''' # Debye debye_fw = Firework(QHAAnalysis(phonon=False, t_min=t_min, t_max=t_max, t_step=t_step, db_file=db_file, tag=tag, metadata=metadata), name="{}-qha_analysis-Debye".format(structure.composition.reduced_formula)) fws.append(debye_fw) if phonon: phonon_supercell_matrix = self.get('phonon_supercell_matrix') # do a Debye run Staticore the phonon, so they can be done in stages. phonon_fw = Firework(QHAAnalysis(phonon=True, t_min=t_min, t_max=t_max, t_step=t_step, db_file=db_file, tag=tag, metadata=metadata), parents=debye_fw, name="{}-qha_analysis-phonon".format(structure.composition.reduced_formula)) fws.append(phonon_fw) ''' strname = "{}:{}".format(structure.composition.reduced_formula, 'QHA') wfs = Workflow(fws, name=strname, metadata=metadata) wfs = Customizing_Workflows(wfs, powerups_options=powerups_options) if not test: lpad.add_wf(wfs) else: # failure to meet the tolerance if len(volumes ) == 0: #self.error == 1e10: # Bad initial running set pass_result_error() else: # fitting fails tol_error() import json with open('EV_check_summary.json', 'w') as fp: json.dump(EVcheck_result, fp, indent=4)
def run_task(self, fw_spec): ''' run_num: maximum number of appending VASP running; this limitation is to avoid always running due to bad settings; only for internal usage; Important args: tolerance: acceptable value for average RMS, recommend >= 0.005; threshold: total point number above the value should be reduced, recommend < 16 or much time to run; del_limited: maximum deletion ration for large results; vol_spacing: the maximum ratio step between two volumes, larger step will be inserted points to calculate; ''' max_run = 10 deformations = self.get('deformations') or [] db_file = self['db_file'] tag = self['tag'] vasp_cmd = self['vasp_cmd'] metadata = self['metadata'] relax_path = self['relax_path'] or '' run_num = self.get('run_num') or 0 tolerance = self.get('tolerance') or 0.005 threshold = self.get('threshold') or 14 del_limited = self.get('del_limited') or 0.3 vol_spacing = self.get('vol_spacing') or 0.03 t_min = self.get('t_min') or 5 t_max = self.get('t_max') or 2000 t_step = self.get('t_step') or 5 phonon = self.get('phonon') or False phonon_supercell_matrix = self.get('phonon_supercell_matrix') or None verbose = self.get('verbose') or False modify_incar_params = self.get('modify_incar_params') or {} modify_kpoints_params = self.get('modify_kpoints_params') or {} Pos_Shape_relax = self.get('Pos_Shape_relax') or False symmetry_tolerance = self.get('symmetry_tolerance') or None run_num += 1 relax_path, Pos_Shape_relax = check_relax_path(relax_path, db_file, tag, Pos_Shape_relax) if relax_path == '': print(''' ####################################################################### # # # Cannot find relax path for static calculations, exit! # # You can modify the tag and run again! # # # ####################################################################### ''') return from pymatgen.io.vasp.inputs import Poscar poscar = Poscar.from_file(relax_path + '/CONTCAR') structure = poscar.structure if phonon: if not consistent_check_db(db_file, tag): print('Please check DB, DFTTK running ended!') return volumes, energies, dos_objs = self.get_orig_EV(db_file, tag) vol_adds = self.check_deformations_in_volumes(deformations, volumes, structure.volume) if (len(vol_adds)) == 0: self.check_points(db_file, metadata, tolerance, threshold, del_limited, volumes, energies, verbose) else: self.correct = True self.error = 1e10 EVcheck_result = {} EVcheck_result['append_run_num'] = run_num EVcheck_result['correct'] = self.correct EVcheck_result['volumes'] = volumes EVcheck_result['energies'] = energies EVcheck_result['tolerance'] = tolerance EVcheck_result['threshold'] = threshold EVcheck_result['vol_spacing'] = vol_spacing EVcheck_result['error'] = self.error EVcheck_result['metadata'] = metadata if self.correct: vol_orig = structure.volume if (len(vol_adds)) == 0: volume, energy, dos_obj = self.gen_volenergdos(self.points, volumes, energies, dos_objs) vol_adds = self.check_vol_coverage(volume, vol_spacing, vol_orig, run_num, energy, structure, dos_obj, phonon, db_file, tag, t_min, t_max, t_step, EVcheck_result) # Normalized to 1 EVcheck_result['sellected'] = volume EVcheck_result['append'] = (vol_adds * vol_orig).tolist() # Marked as adopted in db mark_adopted(tag, db_file, volume) lpad = LaunchPad.auto_load() fws = [] if len(vol_adds) > 0: # VASP calculations need to append if run_num < max_run: # Do VASP and check again print('Appending the volumes of : %s to calculate in VASP!' %(vol_adds * vol_orig).tolist()) calcs = [] vis_relax = RelaxSet(structure) vis_static = StaticSet(structure) isif = 5 if 'infdet' in relax_path else 4 for vol_add in vol_adds: if Pos_Shape_relax: ps_relax_fw = OptimizeFW(structure, scale_lattice=vol_add, symmetry_tolerance=None, modify_incar = {'ISIF': isif}, job_type='normal', name='Pos_Shape_%.3f-relax' %(vol_add * vol_orig), prev_calc_loc=relax_path, vasp_input_set=vis_relax, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, Pos_Shape_relax = True, modify_incar_params=modify_incar_params, modify_kpoints_params = modify_kpoints_params, parents=None) calcs.append(ps_relax_fw) fws.append(ps_relax_fw) static = StaticFW(structure, name = 'structure_%.3f-static' %(vol_add * vol_orig), vasp_input_set=vis_static, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, prev_calc_loc=True, parents=ps_relax_fw) else: static = StaticFW(structure, scale_lattice=vol_add, name = 'structure_%.3f-static' %(vol_add * vol_orig), vasp_input_set=vis_static, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, prev_calc_loc=relax_path, parents=None) fws.append(static) calcs.append(static) if phonon: visphonon = ForceConstantsSet(structure) phonon_fw = PhononFW(structure, phonon_supercell_matrix, t_min=t_min, t_max=t_max, t_step=t_step, name='structure_%.3f-phonon' %(vol_add * vol_orig), vasp_input_set=visphonon, vasp_cmd=vasp_cmd, db_file=db_file, metadata=metadata, prev_calc_loc=True, parents=static) fws.append(phonon_fw) calcs.append(phonon_fw) check_result = Firework(EVcheck_QHA(db_file = db_file, tag = tag, relax_path = relax_path, tolerance = tolerance, threshold = threshold, vol_spacing = vol_spacing, vasp_cmd = vasp_cmd, run_num = run_num, metadata = metadata, t_min = t_min, t_max = t_max, t_step = t_step, phonon = phonon, phonon_supercell_matrix = phonon_supercell_matrix, symmetry_tolerance = symmetry_tolerance, modify_incar_params = modify_incar_params, verbose = verbose, Pos_Shape_relax = Pos_Shape_relax, modify_kpoints_params = modify_kpoints_params), parents = calcs, name='%s-EVcheck_QHA' %structure.composition.reduced_formula) fws.append(check_result) strname = "{}:{}".format(structure.composition.reduced_formula, 'EV_QHA_Append') wfs = Workflow(fws, name = strname, metadata=metadata) if modify_incar_params != {}: from dfttk.utils import add_modify_incar_by_FWname add_modify_incar_by_FWname(wfs, modify_incar_params = modify_incar_params) if modify_kpoints_params != {}: from dfttk.utils import add_modify_kpoints_by_FWname add_modify_kpoints_by_FWname(wfs, modify_kpoints_params = modify_kpoints_params) lpad.add_wf(wfs) else: print(''' ####################################################################### # # # Too many appended VASP running times, abort! # # Please check VASP setting! # # # ####################################################################### ''') else: # No need to do more VASP calculation, QHA could be running print('Success in Volumes-Energies checking, enter QHA ...') # Debye debye_fw = Firework(QHAAnalysis(phonon=False, t_min=t_min, t_max=t_max, t_step=t_step, db_file=db_file, tag=tag, metadata=metadata), name="{}-qha_analysis-Debye".format(structure.composition.reduced_formula)) fws.append(debye_fw) if phonon: phonon_supercell_matrix = self.get('phonon_supercell_matrix') # do a Debye run before the phonon, so they can be done in stages. phonon_fw = Firework(QHAAnalysis(phonon=True, t_min=t_min, t_max=t_max, t_step=t_step, db_file=db_file, tag=tag, metadata=metadata), parents=debye_fw, name="{}-qha_analysis-phonon".format(structure.composition.reduced_formula)) fws.append(phonon_fw) strname = "{}:{}".format(structure.composition.reduced_formula, 'QHA') wfs = Workflow(fws, name = strname, metadata=metadata) lpad.add_wf(wfs) else: # failure to meet the tolerance if len(volumes) == 0: #self.error == 1e10: # Bad initial running set print(''' ####################################################################### # # # "passinitrun = True" could not set while initial results absent. # # # ####################################################################### ''') else: # fitting fails print(''' ####################################################################### # # # Can not achieve the tolerance requirement, abort! # # # ####################################################################### ''') import json with open('E-V check_summary.json', 'w') as fp: json.dump(EVcheck_result, fp)