def print_neb_energy( self ): image_00_energy = final_energy_from_outcar( '00/OUTCAR' ) print( "reference energy: {} eV".format( image_00_energy ) ) neb = NEBAnalysis.from_dir( '.' ) print( "neb image energies:" ) for i, e in enumerate( neb.energies ): print( " - {:02d}: {:10.6f} eV".format( i, e ) )
def runTest(self): neb_analysis1 = NEBAnalysis.from_dir(os.path.join (test_dir, 'neb1', 'neb')) neb_analysis1_from_dict = NEBAnalysis.from_dict(neb_analysis1.as_dict()) json_data = json.dumps(neb_analysis1.as_dict()) neb_dict = json.loads(json_data) neb_analysis1_from_json_data = NEBAnalysis.from_dict(neb_dict) self.assertArrayAlmostEqual(neb_analysis1.energies[0], -255.97992669000001) self.assertArrayAlmostEqual(neb_analysis1.energies[3], -255.84261996000001) self.assertArrayAlmostEqual(neb_analysis1.r, neb_analysis1_from_dict.r) self.assertArrayAlmostEqual(neb_analysis1.energies, neb_analysis1_from_dict.energies) self.assertArrayAlmostEqual(neb_analysis1.forces, neb_analysis1_from_dict.forces) self.assertEqual(neb_analysis1.structures, neb_analysis1_from_dict.structures) self.assertArrayAlmostEqual(neb_analysis1.r, neb_analysis1_from_json_data.r) self.assertArrayAlmostEqual(neb_analysis1.energies, neb_analysis1_from_json_data.energies) self.assertArrayAlmostEqual(neb_analysis1.forces, neb_analysis1_from_json_data.forces) self.assertEqual(neb_analysis1.structures, neb_analysis1_from_json_data.structures) self.assertArrayAlmostEqual(neb_analysis1.get_extrema()[1][0], (0.50023335723480078, 325.20043063935128)) neb_analysis1.setup_spline(spline_options={'saddle_point': 'zero_slope'}) self.assertArrayAlmostEqual(neb_analysis1.get_extrema()[1][0], (0.50023335723480078, 325.20003984140203)) with open(os.path.join(test_dir, 'neb2', 'neb_analysis2.json'), 'r') as f: neb_analysis2_dict = json.load(f) neb_analysis2 = NEBAnalysis.from_dict(neb_analysis2_dict) self.assertArrayAlmostEqual(neb_analysis2.get_extrema()[1][0], (0.37255257367467326, 562.40825334519991)) neb_analysis2.setup_spline(spline_options={'saddle_point': 'zero_slope'}) self.assertArrayAlmostEqual(neb_analysis2.get_extrema()[1][0], (0.30371133723478794, 528.46229631648691))
def print_neb_energy(self): image_00_energy = final_energy_from_outcar('00/OUTCAR') print("reference energy: {} eV".format(image_00_energy)) neb = NEBAnalysis.from_dir('.') print("neb image energies:") for i, e in enumerate(neb.energies): print(" - {:02d}: {:10.6f} eV".format(i, e))
def from_directory(path=None, job_script_filename=None, load_outputs=True): """ Builds VaspNEBjob object from data stored in a directory. Inputs dict is constructed by reading with Pymatgen INCAR, KPOINTS and POTCAR and creating a series of Structure objects read from POSCARs in the images folders. Inputs is thus a dict with "structures", "INCAR","KPOINTS","POTCAR" as keys. Output files are read usign Pymatgen NEBAnalysis and Vasprun classes. Job settings are read from the job script file. Parameters ---------- path : (str) Path were job data is stored. If None the current wdir is used. The default is None. job_script_filename : (str), optional Filename of job script. The default is set in the config file. Returns ------- VaspNEBJob object. """ inputs = {} structures = [] path = path if path else os.getcwd() path = op.abspath(path) dirs = [d[0] for d in os.walk(path)] for d in dirs: image_name = op.relpath(d, start=path) if all( c.isdigit() for c in list(image_name) ): #check if folder is image (all characters in folder rel path need to be numbers) image_path = d structure = Poscar.from_file(op.join(image_path, 'POSCAR')).structure structures.append(structure) inputs['structures'] = structures inputs['INCAR'] = Incar.from_file(op.join(path, 'INCAR')) inputs['KPOINTS'] = Kpoints.from_file(op.join(path, 'KPOINTS')) inputs['POTCAR'] = Potcar.from_file(op.join(path, 'POTCAR')) outputs = {} if load_outputs: try: outputs['NEBAnalysis'] = NEBAnalysis.from_dir(path) except: print( 'Warning: NEB output reading with NEBAnalysis in "%s" failed' % path) outputs['NEBAnalysis'] = None job_script_filename = job_script_filename if job_script_filename else ScriptHandler( ).filename s = ScriptHandler.from_file(path, filename=job_script_filename) job_settings = s.settings return VaspNEBJob(path, inputs, job_settings, outputs, job_script_filename)
def neb2dim(neb_dir, dimer_dir, ts_i=None): if not ts_i: neb_dir = os.path.abspath(neb_dir) dimer_dir = os.path.abspath(dimer_dir) try: energies = NEBAnalysis.from_dir(neb_dir).energies except: if input('Failed, do: rm ' + neb_dir + '*/*.xyz and try again? (y)') == 'y': os.system('rm ' + neb_dir + '/*/*.xyz') energies = NEBAnalysis.from_dir(neb_dir).energies else: raise Exception('Could not read NEB dir') ts_i = list(energies).index(energies.max()) print('Copying TS directory {}'.format(str(ts_i).zfill(2))) if not os.path.exists(dimer_dir): os.makedirs(dimer_dir) for f in os.listdir(os.path.join(neb_dir, str(ts_i).zfill(2))): shutil.copy(os.path.join(neb_dir, str(ts_i).zfill(2), f), dimer_dir) for f in ['INCAR', 'KPOINTS', 'POTCAR']: shutil.copy(os.path.join(neb_dir, f), dimer_dir) print('Modifying INCAR') incar = Incar.from_file(os.path.join(dimer_dir, 'INCAR')) incar['ICHAIN'] = 2 incar['EDIFF'] = 1e-7 incar['NSW'] = 5000 if 'neb' in incar['SYSTEM']: incar['SYSTEM'] = incar['SYSTEM'].replace('neb', 'dim') else: incar['SYSTEM'] = incar['SYSTEM'] + ' dim' for neb_setting in ['IMAGES', 'LCLIMB']: if neb_setting in incar: del incar[neb_setting] incar.write_file(os.path.join(dimer_dir, 'INCAR')) print('Making MODECAR') mode1 = os.path.join(neb_dir, str(ts_i - 1).zfill(2)) mode2 = os.path.join(neb_dir, str(ts_i + 1).zfill(2)) cwd = os.path.abspath('.') os.chdir(dimer_dir) os.system('modemake.pl ' + mode1 + '/CONTCAR ' + mode2 + '/CONTCAR &> /dev/null') os.chdir(cwd)
def add_NEB(collection, material, directory, other_info={}, other_files=[]): """ :param collection: str Name of Collection for Database :param material: str name of Material that will be added to database :param directory: str NEB directory that will be added to Database :param other_info: other_info that can be included :param other_files: other_files that can be included, most files included here will be added from all image directories :return: pymongo.results.InsertOneResult """ from pymatgen.analysis.transition_state import NEBAnalysis # preparing variables incar = Incar.from_file(os.path.join(directory, 'INCAR')) images = incar['IMAGES'] subdirs = [ str(i).zfill(2) for i in range(images+2) ] # Setting up NEB files os.chdir(directory) # nebbarrier = File_Management.file_to_dict(subprocess.check_output('nebbarrier.pl ; cat neb.dat', shell=True), # ['Image', 'Distance', 'Energy', 'Spring Forces' , 'Image_Duplicate'] ) # nebef = File_Management.file_to_dict(subprocess.check_output(['nebef.pl']), # ['Image', 'Force', 'Energy-Absolute', 'Energy-Relative'] ) # nebefs = File_Management.file_to_dict(subprocess.check_output(['nebefs.pl']).replace(b'Rel Energy', b'Rel_Energy')) # Splits on whitespace, label must be one word other_info['images'] = images # other_info['nebbarrier'] = nebbarrier # other_info['nebef'] = nebef # other_info['nebefs'] = nebefs neb = NEBAnalysis.from_dir('.') other_info['energy'] = max(neb.energies) other_info['energies'] = list(neb.energies) max_i = list(neb.energies).index(max(neb.energies)) new_files = [] for i in range(images+2): dir = str(i).zfill(2) other_info['poscar_{}'.format(dir)] = Poscar.from_file('{}/{}'.format(dir,'POSCAR')).as_dict() for name, location in other_files: new_files.append(('{}_{}'.format(name,dir), '{}/{}'.format(dir,location))) (db, fs, client) = load_db() if entry_exists(db[collection], {'energy' : max(neb.energies), 'energies' : list(neb.energies)}): print('Identical Entry Exists') client.close() return False client.close() add_vasp_run(collection, material, 'INCAR', 'KPOINTS', 'POTCAR', os.path.join(str(max_i).zfill(2), 'CONTCAR'), 'vasprun.xml', other_info=other_info, other_files=new_files) return
def show_path(directory, filename): """ Show the final migration for a NEB calculation. Returns: """ # TODO This is quite inefficient, since the NEBAnalysis script also # parses the OUTCAR files. However, this was the fastest solution # implementation wise. Improve when feeling less lazy. neb = NEBAnalysis.from_dir(directory) transition_structure = neb.structures[0].copy() for structure in neb.structures[1:]: for site in structure: transition_structure.append(site.specie, site.frac_coords) transition_structure.to("cif", filename)
def get_outputs(self, sync=False, get_output_properties=True): """ Read outputs from Job directory """ if sync: self.sync_from_hpc() outputs = {} path = self.path try: outputs['NEBAnalysis'] = NEBAnalysis.from_dir(path) except: print( 'Warning: NEB output reading with NEBAnalysis in "%s" failed' % path) outputs['NEBAnalysis'] = None self.outputs = outputs if get_output_properties: self.get_output_properties() return
def get_barrier(directory, method="pymatgen", show_plot=False): """ Plot the migration barrier of a transition in a directory. Args: directory (str): method (str): Returns: """ if method == "pymatgen": # The pymatgen.analysis.transition_state module has an object that # allows you to neb = NEBAnalysis.from_dir(directory, relaxation_dirs=('initial', 'final')) if show_plot: neb.get_plot().show() elif method == "dimer": # This method makes some assumptions about the directory structure # for it to work properly: # # - The image directories are digits, and there are no # other directories which are digits. # - The directory in which the nudged elastic band was performed # contains the dimer indices, delimited by '_', and with no other # numbers delimited in such a way present. if os.path.exists(os.path.join(directory, "neb_data.json")): neb = DimerNEBAnalysis.from_file( os.path.join(directory, "neb_data.json")) else: neb = DimerNEBAnalysis.from_dir( directory, spline_options={"saddle_point": "zero_slope"}) neb.to("json", os.path.join(directory, "neb_data.json")) if show_plot: neb.get_plot(label_barrier=False).show() else: raise NameError("Method for gathering NEB data not recognised.")
def runTest(self): neb_analysis = NEBAnalysis.from_dir(os.path.join(test_dir, 'neb'), relaxation_dirs=(os.path.join(test_dir, 'start'), os.path.join(test_dir, 'end'))) neb_analysis2 = NEBAnalysis.from_dict(neb_analysis.as_dict()) json_data = json.dumps(neb_analysis.as_dict()) neb_dict = json.loads(json_data) neb_analysis3 = NEBAnalysis.from_dict(neb_dict) self.assertArrayAlmostEqual(neb_analysis.r, neb_analysis2.r) self.assertArrayAlmostEqual(neb_analysis.energies, neb_analysis2.energies) self.assertArrayAlmostEqual(neb_analysis.forces, neb_analysis2.forces) self.assertEqual(neb_analysis.structures, neb_analysis2.structures) self.assertArrayAlmostEqual(neb_analysis.r, neb_analysis3.r) self.assertArrayAlmostEqual(neb_analysis.energies, neb_analysis3.energies) self.assertArrayAlmostEqual(neb_analysis.forces, neb_analysis3.forces) self.assertEqual(neb_analysis.structures, neb_analysis3.structures) self.assertAlmostEqual(neb_analysis.get_extrema()[1][0], (0.50023335723480078, 325.20043063935128))
# Diffusion_elements = ['Zr'] # Transition_Paths = ['01-19', '37-59', '59-01'] Transition_Paths = ['01-19', '37-59', '59-01'] OUTCAR_root = '/mnt/c/Users/jackx/OneDrive/Calculation_Data/TC17_TI80/M{0}_S{1}_single'.format( Module_Number, Situation_Number) figure_path = '/mnt/c/Users/jackx/OneDrive/Calculation_Data/TC17_TI80/figure/M{0}_S{1}_single'.format( Module_Number, Situation_Number) if not os.path.exists(figure_path): os.makedirs(figure_path) for Transition_Path in Transition_Paths: fig, ax = plt.subplots(figsize=(8, 6)) for Diffusion_element in Diffusion_elements: OUTCAR_DIR = "{0}/{1}/{2}".format(OUTCAR_root, Diffusion_element, Transition_Path) Neb_data = NEBAnalysis.from_dir(OUTCAR_DIR) x = Neb_data.r / Neb_data.r[-1] y = Neb_data.energies - Neb_data.energies[0] f = interp1d(x, y, kind='cubic') xx = np.linspace(x.min(), x.max(), 100) ax.scatter(x, y * 1000, s=70) ax.plot(xx, f(xx) * 1000, label=Diffusion_element, linewidth=3) ax.legend() plt.xlim(0, 1) plt.xlabel('Reaction Coordinate', fontsize=25) plt.ylabel('Energy(meV)', fontsize=25) plt.tick_params(labelsize=18) axis = plt.gca() bwith = 2 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in'
def get_nebs_analysis(cls, wf): assert wf.metadata['workflow_class'] == cls.workflow_class assert wf.metadata['workflow_module'] == cls.workflow_module terminal_start_step_index = -1 terminal_start_final_fw_id = None terminal_end_step_index = -1 terminal_end_final_fw_id = None neb_tasks_step_index = {} neb_tasks_step_final_fw_id = {} for fw_id, fw in wf.id_fw.items(): if 'SRC_task_index' in fw.spec: if fw.tasks[-1].src_type != 'run': continue task_index = fw.spec['SRC_task_index'] if re.match("\<neb\d\>", task_index.task_type): if task_index.task_type not in neb_tasks_step_index: neb_tasks_step_index[ task_index.task_type] = task_index.index neb_tasks_step_final_fw_id[ task_index.task_type] = fw_id else: if task_index.index > neb_tasks_step_index[ task_index.task_type]: neb_tasks_step_index[ task_index.task_type] = task_index.index neb_tasks_step_final_fw_id[ task_index.task_type] = fw_id elif task_index.task_type == 'MPRelaxVasp-start': if task_index.index > terminal_start_step_index: terminal_start_step_index = task_index.index terminal_start_final_fw_id = fw_id elif task_index.task_type == 'MPRelaxVasp-end': if task_index.index > terminal_end_step_index: terminal_end_step_index = task_index.index terminal_end_final_fw_id = fw_id if terminal_start_final_fw_id is None: raise RuntimeError('No terminal-start relaxation found ...') if terminal_end_final_fw_id is None: raise RuntimeError('No terminal-end relaxation found ...') if len(neb_tasks_step_index) == 0: raise RuntimeError('No NEB analysis found ...') # Terminal start dir terminal_start_fw = wf.id_fw[terminal_start_final_fw_id] terminal_start_last_launch = (terminal_start_fw.archived_launches + terminal_start_fw.launches)[-1] terminal_start_run_dir = terminal_start_last_launch.launch_dir # Terminal end dir terminal_end_fw = wf.id_fw[terminal_end_final_fw_id] terminal_end_last_launch = (terminal_end_fw.archived_launches + terminal_end_fw.launches)[-1] terminal_end_run_dir = terminal_end_last_launch.launch_dir nebs_analysis = [] for ineb in range(1, len(neb_tasks_step_index) + 1): neb_task = 'neb{:d}'.format(ineb) nebfw = wf.id_fw[neb_tasks_step_final_fw_id[neb_task]] last_launch = (nebfw.archived_launches + nebfw.launches)[-1] neb_analysis = NEBAnalysis.from_dir( last_launch.launch_dir, relaxation_dirs=(terminal_start_run_dir, terminal_end_run_dir)) nebs_analysis.append(neb_analysis) return { 'nebs_analysis': [neb_analysis.as_dict() for neb_analysis in nebs_analysis] }
def test_combine_neb_plots(self): neb_dir = os.path.join(test_dir, "neb1", "neb") neb_analysis = NEBAnalysis.from_dir(neb_dir) combine_neb_plots([neb_analysis, neb_analysis])
# Neb_Dir = '{}{}{}/NEB_DATA'.format(Work_Dir, Diffusion_structure, Diffusion_elements) # OUTCAR_root = '/mnt/c/Users/jackx/OneDrive/Calculation_Data/TC17_TI80/M{0}_S{1}_single'.format(Module_Number, # Situation_Number) # figure_path = '/mnt/c/Users/jackx/OneDrive/Calculation_Data/TC17_TI80/figure/M{0}_S{1}_single'.format(Module_Number, # Situation_Number) if not os.path.exists(Fig_Dir): os.makedirs(Fig_Dir) for Transition_Path in Transition_Paths: fig, ax = plt.subplots(figsize=(8, 6)) for Diffusion_element in Diffusion_elements: Neb_Dir = '{}/NEB_Results{}/{}/{}/{}'.format( Work_Dir, Diffusion_structure, Diffusion_Method, Diffusion_element, Transition_Path) # OUTCAR_DIR = "{0}/{1}/{2}".format(Neb_Dir, Diffusion_element, Transition_Path) Neb_data = NEBAnalysis.from_dir(Neb_Dir) x = Neb_data.r / Neb_data.r[-1] y = Neb_data.energies - Neb_data.energies[0] f = interp1d(x, y, kind='cubic') xx = np.linspace(x.min(), x.max(), 100) ax.scatter(x, y * 1000, s=70) ax.plot(xx, f(xx) * 1000, label=Diffusion_element, linewidth=3) ax.legend() plt.xlim(0, 1) plt.xlabel('Reaction Coordinate', fontsize=25) plt.ylabel('Energy(meV)', fontsize=25) plt.tick_params(labelsize=18) axis = plt.gca() bwith = 2 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in'
def test_combine_neb_plots(self): neb_dir = os.path.join(test_dir, 'neb1', 'neb') neb_analysis = NEBAnalysis.from_dir(neb_dir) combine_neb_plots([neb_analysis, neb_analysis])
def run_task(self, fw_spec): from magdesign.diffusion.neb_structures import neb_structures_insert_in_existing terminal_start_rundir = fw_spec['previous_fws'][ self.terminal_start_task_type][0]['dir'] terminal_end_rundir = fw_spec['previous_fws'][ self.terminal_end_task_type][0]['dir'] if 'structures' in fw_spec: if fw_spec['structures'] is not None: structs = neb_structures_insert_in_existing( fw_spec['structures'], n_insert=self.n_insert) else: # Get the structures from the previous nebs ... if len(fw_spec['previous_fws'][self.prev_neb_task_type]) != 1: raise RuntimeError( 'Multiple or no fws with task_type "{}"'.format( self.prev_neb_task_type)) prev_neb_rundir = fw_spec['previous_fws'][ self.prev_neb_task_type][0]['dir'] prev_neb_analysis = NEBAnalysis.from_dir( prev_neb_rundir, relaxation_dirs=(terminal_start_rundir, terminal_end_rundir)) structs = neb_structures_insert_in_existing( prev_neb_analysis.structures, n_insert=self.n_insert) else: if fw_spec['terminal_start'] is not None: structs = neb_structures_insert_in_existing( [fw_spec['terminal_start'], fw_spec['terminal_end']], n_insert=self.n_insert) else: # Get the terminals from the relaxation of the terminals. if len(fw_spec['previous_fws'][ self.terminal_start_task_type]) != 1: raise RuntimeError( 'Multiple or no fws with task_type "{}"'.format( self.terminal_start_task_type)) if len(fw_spec['previous_fws'][ self.terminal_end_task_type]) != 1: raise RuntimeError( 'Multiple or no fws with task_type "{}"'.format( self.terminal_end_task_type)) terminal_start_rundir = fw_spec['previous_fws'][ self.terminal_start_task_type][0]['dir'] terminal_end_rundir = fw_spec['previous_fws'][ self.terminal_end_task_type][0]['dir'] terminal_start_vasprun = Vasprun( os.path.join(terminal_start_rundir, 'vasprun.xml')) terminal_end_vasprun = Vasprun( os.path.join(terminal_end_rundir, 'vasprun.xml')) terminal_start_structure = terminal_start_vasprun.final_structure terminal_end_structure = terminal_end_vasprun.final_structure structs = neb_structures_insert_in_existing( [terminal_start_structure, terminal_end_structure], n_insert=self.n_insert) if self.climbing_image: neb_vis = MPcNEBSet(structures=structs, user_incar_settings=self.user_incar_settings) task_helper = MPcNEBTaskHelper() else: neb_vis = MPNEBSet(structures=structs, user_incar_settings=self.user_incar_settings) task_helper = MPNEBTaskHelper() if 'additional_controllers' in fw_spec: additional_controllers = fw_spec['additional_controllers'] fw_spec.pop('additional_controllers') else: additional_controllers = [ WalltimeController(), MemoryController(), VaspNEBValidatorController() ] control_procedure = ControlProcedure( controllers=additional_controllers) if self.task_index is None: # Define the task_index as "MPNEBVaspN" where N is the number of structures in the NEB (e.g. 3 when two end # points plus one structure are computed) if self.climbing_image: task_index = 'MPcNEBVasp{:d}'.format(len(structs)) else: task_index = 'MPNEBVasp{:d}'.format(len(structs)) else: task_index = self.task_index task_index = SRCTaskIndex.from_any(task_index) task_type = task_index.task_type src_fws = createVaspSRCFireworks(vasp_input_set=neb_vis, task_helper=task_helper, task_type=task_type, control_procedure=control_procedure, custodian_handlers=[], max_restarts=10, src_cleaning=None, task_index=task_index, spec={ 'additional_vasp_wf_info': { 'terminal_start_run_dir': terminal_start_rundir, 'terminal_end_run_dir': terminal_end_rundir } }, setup_spec_update=None, run_spec_update=None) wf = Workflow(fireworks=src_fws['fws'], links_dict=src_fws['links_dict']) return FWAction(detours=[wf])
def test_combine_neb_plots(): neb_dir = os.path.join(test_dir, 'neb1', 'neb') neb_analysis = NEBAnalysis.from_dir(neb_dir) combine_neb_plots([neb_analysis, neb_analysis])
#! /usr/bin/env python3 import numpy as np import pandas as pd from pymatgen.analysis.transition_state import NEBAnalysis # http://pymatgen.org/_modules/pymatgen/analysis/transition_state.html neb = NEBAnalysis.from_dir('.') output = np.vstack((neb.energies, neb.r, neb.forces)).T df = pd.DataFrame(output, columns=['energy', 'distance', 'force']) df['relative energy'] = df.energy - df.energy.min() print(df)
def run_task(self, fw_spec): from magdesign.diffusion.neb_structures import neb_structures_insert_in_existing terminal_start_rundir = fw_spec['previous_fws'][self.terminal_start_task_type][0]['dir'] terminal_end_rundir = fw_spec['previous_fws'][self.terminal_end_task_type][0]['dir'] if 'structures' in fw_spec: if fw_spec['structures'] is not None: structs = neb_structures_insert_in_existing(fw_spec['structures'], n_insert=self.n_insert) else: # Get the structures from the previous nebs ... if len(fw_spec['previous_fws'][self.prev_neb_task_type]) != 1: raise RuntimeError('Multiple or no fws with task_type "{}"'.format(self.prev_neb_task_type)) prev_neb_rundir = fw_spec['previous_fws'][self.prev_neb_task_type][0]['dir'] prev_neb_analysis = NEBAnalysis.from_dir(prev_neb_rundir, relaxation_dirs=(terminal_start_rundir, terminal_end_rundir)) structs = neb_structures_insert_in_existing(prev_neb_analysis.structures, n_insert=self.n_insert) else: if fw_spec['terminal_start'] is not None: structs = neb_structures_insert_in_existing([fw_spec['terminal_start'], fw_spec['terminal_end']], n_insert=self.n_insert) else: # Get the terminals from the relaxation of the terminals. if len(fw_spec['previous_fws'][self.terminal_start_task_type]) != 1: raise RuntimeError('Multiple or no fws with task_type "{}"'.format(self.terminal_start_task_type)) if len(fw_spec['previous_fws'][self.terminal_end_task_type]) != 1: raise RuntimeError('Multiple or no fws with task_type "{}"'.format(self.terminal_end_task_type)) terminal_start_rundir = fw_spec['previous_fws'][self.terminal_start_task_type][0]['dir'] terminal_end_rundir = fw_spec['previous_fws'][self.terminal_end_task_type][0]['dir'] terminal_start_vasprun = Vasprun(os.path.join(terminal_start_rundir, 'vasprun.xml')) terminal_end_vasprun = Vasprun(os.path.join(terminal_end_rundir, 'vasprun.xml')) terminal_start_structure = terminal_start_vasprun.final_structure terminal_end_structure = terminal_end_vasprun.final_structure structs = neb_structures_insert_in_existing([terminal_start_structure, terminal_end_structure], n_insert=self.n_insert) if self.climbing_image: neb_vis = MPcNEBSet(structures=structs, user_incar_settings=self.user_incar_settings) task_helper = MPcNEBTaskHelper() else: neb_vis = MPNEBSet(structures=structs, user_incar_settings=self.user_incar_settings) task_helper = MPNEBTaskHelper() if 'additional_controllers' in fw_spec: additional_controllers = fw_spec['additional_controllers'] fw_spec.pop('additional_controllers') else: additional_controllers = [WalltimeController(), MemoryController(), VaspNEBValidatorController()] control_procedure = ControlProcedure(controllers=additional_controllers) if self.task_index is None: # Define the task_index as "MPNEBVaspN" where N is the number of structures in the NEB (e.g. 3 when two end # points plus one structure are computed) if self.climbing_image: task_index = 'MPcNEBVasp{:d}'.format(len(structs)) else: task_index = 'MPNEBVasp{:d}'.format(len(structs)) else: task_index = self.task_index task_index = SRCTaskIndex.from_any(task_index) task_type = task_index.task_type src_fws = createVaspSRCFireworks(vasp_input_set=neb_vis, task_helper=task_helper, task_type=task_type, control_procedure=control_procedure, custodian_handlers=[], max_restarts=10, src_cleaning=None, task_index=task_index, spec={'additional_vasp_wf_info': {'terminal_start_run_dir': terminal_start_rundir, 'terminal_end_run_dir': terminal_end_rundir}}, setup_spec_update=None, run_spec_update=None) wf = Workflow(fireworks=src_fws['fws'], links_dict=src_fws['links_dict']) return FWAction(detours=[wf])
def get_nebs_analysis(cls, wf): assert wf.metadata['workflow_class'] == cls.workflow_class assert wf.metadata['workflow_module'] == cls.workflow_module terminal_start_step_index = -1 terminal_start_final_fw_id = None terminal_end_step_index = -1 terminal_end_final_fw_id = None neb_tasks_step_index = {} neb_tasks_step_final_fw_id = {} neb_setup_tasks_step_index = {} neb_setup_tasks_step_final_fw_id = {} for fw_id, fw in wf.id_fw.items(): if 'SRC_task_index' in fw.spec: src_type = fw.tasks[-1].src_type if src_type in ['run', 'setup']: task_index = fw.spec['SRC_task_index'] match = re.match("neb\d+$", task_index.task_type) if match and match.string == task_index.task_type: if src_type == 'run': if task_index.task_type not in neb_tasks_step_index: neb_tasks_step_index[task_index.task_type] = task_index.index neb_tasks_step_final_fw_id[task_index.task_type] = fw_id else: if task_index.index > neb_tasks_step_index[task_index.task_type]: neb_tasks_step_index[task_index.task_type] = task_index.index neb_tasks_step_final_fw_id[task_index.task_type] = fw_id elif src_type == 'setup': if task_index.task_type not in neb_setup_tasks_step_index: neb_setup_tasks_step_index[task_index.task_type] = task_index.index neb_setup_tasks_step_final_fw_id[task_index.task_type] = fw_id else: if task_index.index > neb_setup_tasks_step_index[task_index.task_type]: neb_setup_tasks_step_index[task_index.task_type] = task_index.index neb_setup_tasks_step_final_fw_id[task_index.task_type] = fw_id elif task_index.task_type == 'MPRelaxVasp-start': if src_type == 'run': if task_index.index > terminal_start_step_index: terminal_start_step_index = task_index.index terminal_start_final_fw_id = fw_id elif task_index.task_type == 'MPRelaxVasp-end': if src_type == 'run': if task_index.index > terminal_end_step_index: terminal_end_step_index = task_index.index terminal_end_final_fw_id = fw_id if terminal_start_final_fw_id is None: raise RuntimeError('No terminal-start relaxation found ...') if terminal_end_final_fw_id is None: raise RuntimeError('No terminal-end relaxation found ...') if len(neb_tasks_step_index) == 0: raise RuntimeError('No NEB analysis found ...') # Terminal start dir terminal_start_fw = wf.id_fw[terminal_start_final_fw_id] terminal_start_last_launch = (terminal_start_fw.archived_launches + terminal_start_fw.launches)[-1] terminal_start_run_dir = terminal_start_last_launch.launch_dir # Terminal end dir terminal_end_fw = wf.id_fw[terminal_end_final_fw_id] terminal_end_last_launch = (terminal_end_fw.archived_launches + terminal_end_fw.launches)[-1] terminal_end_run_dir = terminal_end_last_launch.launch_dir nebs_analysis = [] nebs_calculations_parameters = [] helper = MPNEBTaskHelper() for ineb in range(1, len(neb_tasks_step_index)+1): neb_task_type = 'neb{:d}'.format(ineb) nebfw = wf.id_fw[neb_tasks_step_final_fw_id[neb_task_type]] last_launch = (nebfw.archived_launches + nebfw.launches)[-1] neb_analysis = NEBAnalysis.from_dir(last_launch.launch_dir, relaxation_dirs=(terminal_start_run_dir, terminal_end_run_dir)) nebs_analysis.append(neb_analysis) nebsetupfw = wf.id_fw[neb_setup_tasks_step_final_fw_id[neb_task_type]] nebsetuptask = nebsetupfw.tasks[-1] neb_vasp_input_set = nebsetuptask.vasp_input_set kpoints_generation_description = get_kpoints_generation_description(neb_vasp_input_set) neb_task = nebfw.tasks[-1] last_launch = (nebfw.archived_launches + nebfw.launches)[-1] helper.set_task(neb_task) helper.task.setup_rundir(last_launch.launch_dir) vasprun = helper.get_vasprun() if vasprun == 'vasprun.xml malformed': incar = helper.get_incar() calculation_parameters = {'origin': 'incar', 'INCAR': incar, 'INCAR_ALL': 'unknown', 'potcar_symbols': 'unknown', 'ENCUT': incar.get('ENCUT', 'DEFAULT'), 'EDIFFG': incar.get('EDIFFG', 'DEFAULT'), 'ISMEAR': incar.get('ISMEAR', 'DEFAULT'), 'SIGMA': incar.get('SIGMA', 'DEFAULT'), 'kpoints_generation_description': kpoints_generation_description} else: calculation_parameters = {'origin': 'vasprun.xml', 'INCAR': vasprun.incar, 'INCAR_ALL': vasprun.parameters, 'potcar_symbols': vasprun.potcar_symbols, 'ENCUT': vasprun.incar['ENCUT'] or vasprun.parameters['ENCUT'], 'EDIFFG': vasprun.incar.get('EDIFFG') or vasprun.parameters.get('EDIFFG'), 'ISMEAR': vasprun.incar.get('ISMEAR') or vasprun.parameters.get('ISMEAR'), 'SIGMA': vasprun.incar.get('SIGMA') or vasprun.parameters.get('SIGMA'), 'kpoints_generation_description': kpoints_generation_description} nebs_calculations_parameters.append(calculation_parameters) return {'nebs_analysis': [neb_analysis.as_dict() for neb_analysis in nebs_analysis], 'nebs_calculations_parameters': nebs_calculations_parameters}