def read_convergence_data(self, data_dir): results = {} if 'G0W0' in data_dir or 'GW0' in data_dir or 'scGW0' in data_dir: run = os.path.join(data_dir, 'vasprun.xml') kpoints = os.path.join(data_dir, 'IBZKPT') if os.path.isfile(run): try: data = Vasprun(run, ionic_step_skip=1) parameters = data.__getattribute__('incar').to_dict bandstructure = data.get_band_structure(kpoints) results = {'ecuteps': parameters['ENCUTGW'], 'nbands': parameters['NBANDS'], 'nomega': parameters['NOMEGA'], 'gwgap': bandstructure.get_band_gap()['energy']} except (IOError, OSError, IndexError, KeyError): pass return results
def test_get_band_structure(self): filepath = os.path.join(test_dir, 'vasprun_Si_bands.xml') vasprun = Vasprun(filepath) bs = vasprun.get_band_structure(kpoints_filename= os.path.join(test_dir, 'KPOINTS_Si_bands')) cbm = bs.get_cbm() vbm = bs.get_vbm() self.assertEqual(cbm['kpoint_index'], [13], "wrong cbm kpoint index") self.assertAlmostEqual(cbm['energy'], 6.2301, "wrong cbm energy") self.assertEqual(cbm['band_index'], {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands") self.assertEqual(vbm['kpoint_index'], [0, 63, 64], "wrong vbm kpoint index") self.assertAlmostEqual(vbm['energy'], 5.6158, "wrong vbm energy") self.assertEqual(vbm['band_index'], {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands") self.assertEqual(vbm['kpoint'].label, "\Gamma", "wrong vbm label") self.assertEqual(cbm['kpoint'].label, None, "wrong cbm label")
def test_get_band_structure(self): filepath = os.path.join(test_dir, 'vasprun_Si_bands.xml') vasprun = Vasprun(filepath) bs = vasprun.get_band_structure(kpoints_filename= os.path.join(test_dir, 'KPOINTS_Si_bands')) cbm = bs.get_cbm() vbm = bs.get_vbm() self.assertEqual(cbm['kpoint_index'], [13], "wrong cbm kpoint index") self.assertAlmostEqual(cbm['energy'], 6.2301, "wrong cbm energy") self.assertEqual(cbm['band_index'], {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands") self.assertEqual(vbm['kpoint_index'], [0, 63, 64], "wrong vbm kpoint index") self.assertAlmostEqual(vbm['energy'], 5.6158, "wrong vbm energy") self.assertEqual(vbm['band_index'], {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands") self.assertEqual(vbm['kpoint'].label, "\Gamma", "wrong vbm label") self.assertEqual(cbm['kpoint'].label, None, "wrong cbm label")
def read_convergence_data(self, data_dir): results = {} if 'G0W0' in data_dir or 'GW0' in data_dir or 'scGW0' in data_dir: run = os.path.join(data_dir, 'vasprun.xml') kpoints = os.path.join(data_dir, 'IBZKPT') if os.path.isfile(run): try: logger.debug(run) print(run) data = Vasprun(run, ionic_step_skip=1) parameters = data.incar.as_dict() bandstructure = data.get_band_structure(kpoints) results = { 'ecuteps': parameters['ENCUTGW'], 'nbands': parameters['NBANDS'], 'nomega': parameters['NOMEGA'], 'gwgap': bandstructure.get_band_gap()['energy'] } print(results) except (IOError, OSError, IndexError, KeyError): pass return results
from pymatgen.io.vaspio.vasp_output import Outcar, Vasprun from pymatgen.electronic_structure import bandstructure import os vasp_dir = os.path.dirname(os.path.abspath(__file__)) vasp_run = Vasprun(os.path.join(vasp_dir,"vasprun.xml")) bs = vasp_run.get_band_structure(kpoints_filename=None, efermi=None,line_mode=False) vbm = bs.get_vbm()['energy'] cbm = bs.get_cbm()['energy'] bandgap = bs.get_band_gap()['energy'] vbm_position = bs.get_vbm()['kpoint_index'] cbm_position = bs.get_cbm()['kpoint_index'] print vbm_position, cbm_position direct = False if vbm_position == cbm_position: direct = True print vbm, cbm, bandgap, direct
from pymatgen.io.vaspio.vasp_input import Kpoints from pymatgen.io.vaspio_set import DictVaspInputSet from pymatgen.matproj.rest import MPRester from pymatgen.io.vaspio.vasp_output import Vasprun from abipy.electrons.scissors import ScissorsBuilder import abipy.data as abidata from abipy.abilab import abiopen, ElectronBandsPlotter MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) try: data = Vasprun('vasprun.xml', ionic_step_skip=1) print(data.converged) bandstructure = data.get_band_structure('../IBZKPT') print('gap: ', bandstructure.get_band_gap()['energy'], ' direct : ', bandstructure.get_band_gap()['direct']) print('cbm: ', bandstructure.get_cbm()['energy'], data.actual_kpoints[bandstructure.get_cbm()['kpoint_index'][0]]) print('vbm: ', bandstructure.get_vbm()['energy'], data.actual_kpoints[bandstructure.get_vbm()['kpoint_index'][0]]) print( 'gap: ', bandstructure.get_cbm()['energy'] - bandstructure.get_vbm()['energy']) print('direct gap: ', bandstructure.get_direct_band_gap()) except (IOError, OSError): print('no vasp output found')
__author__ = 'Qimin' from pymatgen.io.vaspio.vasp_output import Vasprun from pymatgen.electronic_structure.plotter import BSPlotter import os import pickle vasp_dir = os.path.dirname(os.path.abspath(__file__)) vasp_run = Vasprun(os.path.join(vasp_dir,"vasprun.xml")) bs = vasp_run.get_band_structure(line_mode=True) print bs.get_vbm()["energy"] print bs.get_cbm()["energy"] print bs.get_band_gap()["energy"] # The above doesn't work on Vulcan or nano cluster due to a bug in virtualenv. Please use the following line to get band structure data from the cluster. pickle.dump(bs, open("band_structure.dat", "w")) # And then load the pickle object on your local machine. #bs = pickle.load(open("band_structure.dat", "r")) #print BSPlotter(bs).bs_plot_data(zero_to_efermi=True) #BSPlotter(bs).save_plot(filename="1.pdf",img_format="pdf",ylim=None,zero_to_efermi=True,smooth=True)
if __name__ == "__main__": # read data # --------- # kpoints labels labels = [r"$L$", r"$\Gamma$", r"$X$", r"$U,K$", r"$\Gamma$"] # density of states dosrun = Vasprun("./DOS/vasprun.xml") spd_dos = dosrun.complete_dos.get_spd_dos() # bands run = Vasprun("./Bandes/vasprun.xml", parse_projected_eigen=True) bands = run.get_band_structure("./Bandes/KPOINTS", line_mode=True, efermi=dosrun.efermi) # set up matplotlib plot # ---------------------- # general options for plot font = {'family': 'serif', 'size': 24} plt.rc('font', **font) # set up 2 graph with aspec ration 2/1 # plot 1: bands diagram # plot 2: Density of States gs = GridSpec(1, 2, width_ratios=[2, 1]) fig = plt.figure(figsize=(11.69, 8.27)) fig.suptitle("Bands diagram of copper")
from pymatgen.io.vaspio.vasp_input import Kpoints from pymatgen.io.vaspio_set import DictVaspInputSet from pymatgen.matproj.rest import MPRester from pymatgen.io.vaspio.vasp_output import Vasprun from abipy.electrons.scissors import ScissorsBuilder import abipy.data as abidata from abipy.abilab import abiopen, ElectronBandsPlotter MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) try: data = Vasprun('vasprun.xml', ionic_step_skip=1) print(data.converged) bandstructure = data.get_band_structure('../IBZKPT') print('gap: ', bandstructure.get_band_gap()['energy'], ' direct : ', bandstructure.get_band_gap()['direct']) print('cbm: ', bandstructure.get_cbm()['energy'], data.actual_kpoints[bandstructure.get_cbm()['kpoint_index'][0]]) print('vbm: ', bandstructure.get_vbm()['energy'], data.actual_kpoints[bandstructure.get_vbm()['kpoint_index'][0]]) print('gap: ', bandstructure.get_cbm()['energy'] - bandstructure.get_vbm()['energy']) print('direct gap: ', bandstructure.get_direct_band_gap()) except (IOError, OSError): print('no vasp output found') try: # Get the quasiparticle results from the SIGRES.nc database. sigma_file = abiopen(abidata.ref_file("tgw1_9o_DS4_SIGRES.nc")) #sigma_file.plot_qps_vs_e0() qplist_spin = sigma_file.qplist_spin print(qplist_spin)
def assimilate(self, path, launches_coll=None): """ Parses vasp runs. Then insert the result into the db. and return the task_id or doc of the insertion. Returns: If in simulate_mode, the entire doc is returned for debugging purposes. Else, only the task_id of the inserted doc is returned. """ d = self.get_task_doc(path) if self.additional_fields: d.update(self.additional_fields) # always add additional fields, even for failed jobs try: d["dir_name_full"] = d["dir_name"].split(":")[1] d["dir_name"] = get_block_part(d["dir_name_full"]) d["stored_data"] = {} except: print 'COULD NOT GET DIR NAME' pprint.pprint(d) print traceback.format_exc() raise ValueError('IMPROPER PARSING OF {}'.format(path)) if not self.simulate: # Perform actual insertion into db. Because db connections cannot # be pickled, every insertion needs to create a new connection # to the db. conn = MongoClient(self.host, self.port) db = conn[self.database] if self.user: db.authenticate(self.user, self.password) coll = db[self.collection] # Insert dos data into gridfs and then remove it from the dict. # DOS data tends to be above the 4Mb limit for mongo docs. A ref # to the dos file is in the dos_fs_id. result = coll.find_one({"dir_name": d["dir_name"]}) if result is None or self.update_duplicates: if self.parse_dos and "calculations" in d: for calc in d["calculations"]: if "dos" in calc: dos = json.dumps(calc["dos"], cls=MontyEncoder) fs = gridfs.GridFS(db, "dos_fs") dosid = fs.put(dos) calc["dos_fs_id"] = dosid del calc["dos"] d["last_updated"] = datetime.datetime.today() if result is None: if ("task_id" not in d) or (not d["task_id"]): d["task_id"] = "mp-{}".format( db.counter.find_and_modify( query={"_id": "taskid"}, update={"$inc": {"c": 1}})["c"]) logger.info("Inserting {} with taskid = {}" .format(d["dir_name"], d["task_id"])) elif self.update_duplicates: d["task_id"] = result["task_id"] logger.info("Updating {} with taskid = {}" .format(d["dir_name"], d["task_id"])) #Fireworks processing self.process_fw(path, d) try: #Add oxide_type struct=Structure.from_dict(d["output"]["crystal"]) d["oxide_type"]=oxide_type(struct) except: logger.error("can't get oxide_type for {}".format(d["task_id"])) d["oxide_type"] = None #Override incorrect outcar subdocs for two step relaxations if "optimize structure" in d['task_type'] and \ os.path.exists(os.path.join(path, "relax2")): try: run_stats = {} for i in [1,2]: o_path = os.path.join(path,"relax"+str(i),"OUTCAR") o_path = o_path if os.path.exists(o_path) else o_path+".gz" outcar = Outcar(o_path) d["calculations"][i-1]["output"]["outcar"] = outcar.to_dict run_stats["relax"+str(i)] = outcar.run_stats except: logger.error("Bad OUTCAR for {}.".format(path)) try: overall_run_stats = {} for key in ["Total CPU time used (sec)", "User time (sec)", "System time (sec)", "Elapsed time (sec)"]: overall_run_stats[key] = sum([v[key] for v in run_stats.values()]) run_stats["overall"] = overall_run_stats except: logger.error("Bad run stats for {}.".format(path)) d["run_stats"] = run_stats # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = d["pseudo_potential"]["functional"] labels = d["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = {"run_type": d["run_type"], "is_hubbard": d["is_hubbard"], "hubbards": d["hubbards"], "potcar_symbols": symbols} entry = ComputedEntry(Composition(d["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=d["task_id"]) d['is_compatible'] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility' d['is_compatible'] = None #task_type dependent processing if 'static' in d['task_type']: launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) for i in ["conventional_standard_structure", "symmetry_operations", "symmetry_dataset", "refined_structure"]: try: d['stored_data'][i] = launch_doc['action']['stored_data'][i] except: pass #parse band structure if necessary if ('band structure' in d['task_type'] or "Uniform" in d['task_type'])\ and d['state'] == 'successful': launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) vasp_run = Vasprun(zpath(os.path.join(path, "vasprun.xml")), parse_projected_eigen=False) if 'band structure' in d['task_type']: def string_to_numlist(stringlist): g=re.search('([0-9\-\.eE]+)\s+([0-9\-\.eE]+)\s+([0-9\-\.eE]+)', stringlist) return [float(g.group(i)) for i in range(1,4)] for i in ["kpath_name", "kpath"]: d['stored_data'][i] = launch_doc['action']['stored_data'][i] kpoints_doc = d['stored_data']['kpath']['kpoints'] for i in kpoints_doc: kpoints_doc[i]=string_to_numlist(kpoints_doc[i]) bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=True) else: bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=False) bs_json = json.dumps(bs.to_dict, cls=MontyEncoder) fs = gridfs.GridFS(db, "band_structure_fs") bs_id = fs.put(bs_json) d['calculations'][0]["band_structure_fs_id"] = bs_id coll.update({"dir_name": d["dir_name"]}, d, upsert=True) return d["task_id"], d else: logger.info("Skipping duplicate {}".format(d["dir_name"])) return result["task_id"], result else: d["task_id"] = 0 logger.info("Simulated insert into database for {} with task_id {}" .format(d["dir_name"], d["task_id"])) return 0, d
for p in path: if len(labels) != 0: labels[-1] = r"$%s,%s$" % (labels[-1].strip("$"), p[0]) else: labels.append(r"$%s$" % p[0]) for kp in p[1:]: labels.append(r"$%s$" % kp) # density of state dosrun = Vasprun("../../DOS/Cu/vasprun.xml") spd_dos = dosrun.complete_dos.get_spd_dos() # bands run = Vasprun("vasprun.xml", parse_projected_eigen = True) bands = run.get_band_structure("KPOINTS", line_mode = True, efermi = dosrun.efermi) # set up matplotlib plot # ---------------------- # general options for plot font = {'family': 'serif', 'size': 24} plt.rc('font', **font) # set up 2 graph with aspec ration 2/1 # plot 1: bands diagram # plot 2: Density of State gs = GridSpec(1, 2, width_ratios=[2,1]) fig = plt.figure(figsize=(11.69, 8.27)) fig.suptitle("Bands diagram of copper")
def assimilate(self, path, launches_coll=None): """ Parses vasp runs. Then insert the result into the db. and return the task_id or doc of the insertion. Returns: If in simulate_mode, the entire doc is returned for debugging purposes. Else, only the task_id of the inserted doc is returned. """ d = self.get_task_doc(path, self.parse_dos, self.additional_fields) try: d["dir_name_full"] = d["dir_name"].split(":")[1] d["dir_name"] = get_block_part(d["dir_name_full"]) d["stored_data"] = {} except: print 'COULD NOT GET DIR NAME' pprint.pprint(d) print traceback.format_exc() raise ValueError('IMPROPER PARSING OF {}'.format(path)) if not self.simulate: # Perform actual insertion into db. Because db connections cannot # be pickled, every insertion needs to create a new connection # to the db. conn = MongoClient(self.host, self.port) db = conn[self.database] if self.user: db.authenticate(self.user, self.password) coll = db[self.collection] # Insert dos data into gridfs and then remove it from the dict. # DOS data tends to be above the 4Mb limit for mongo docs. A ref # to the dos file is in the dos_fs_id. result = coll.find_one({"dir_name": d["dir_name"]}) if result is None or self.update_duplicates: if self.parse_dos and "calculations" in d: for calc in d["calculations"]: if "dos" in calc: dos = json.dumps(calc["dos"]) fs = gridfs.GridFS(db, "dos_fs") dosid = fs.put(dos) calc["dos_fs_id"] = dosid del calc["dos"] d["last_updated"] = datetime.datetime.today() if result is None: if ("task_id" not in d) or (not d["task_id"]): d["task_id"] = "mp-{}".format( db.counter.find_and_modify( query={"_id": "taskid"}, update={"$inc": {"c": 1}})["c"]) logger.info("Inserting {} with taskid = {}" .format(d["dir_name"], d["task_id"])) elif self.update_duplicates: d["task_id"] = result["task_id"] logger.info("Updating {} with taskid = {}" .format(d["dir_name"], d["task_id"])) #Fireworks processing self.process_fw(path, d) #Override incorrect outcar subdocs for two step relaxations if "optimize structure" in d['task_type'] and \ os.path.exists(os.path.join(path, "relax2")): try: run_stats = {} for i in [1,2]: outcar = Outcar(os.path.join(path,"relax"+str(i),"OUTCAR")) d["calculations"][i-1]["output"]["outcar"] = outcar.to_dict run_stats["relax"+str(i)] = outcar.run_stats except: logger.error("Bad OUTCAR for {}.".format(path)) try: overall_run_stats = {} for key in ["Total CPU time used (sec)", "User time (sec)", "System time (sec)", "Elapsed time (sec)"]: overall_run_stats[key] = sum([v[key] for v in run_stats.values()]) run_stats["overall"] = overall_run_stats except: logger.error("Bad run stats for {}.".format(path)) d["run_stats"] = run_stats #task_type dependent processing if 'static' in d['task_type']: launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) for i in ["conventional_standard_structure", "symmetry_operations", "symmetry_dataset", "refined_structure"]: try: d['stored_data'][i] = launch_doc['action']['stored_data'][i] except: pass #parse band structure if necessary if ('band structure' in d['task_type'] or "Uniform" in d['task_type'])\ and d['state'] == 'successful': launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) vasp_run = Vasprun(os.path.join(path, "vasprun.xml"), parse_projected_eigen=False) if 'band structure' in d['task_type']: def string_to_numlist(stringlist): g=re.search('([0-9\-\.eE]+)\s+([0-9\-\.eE]+)\s+([0-9\-\.eE]+)', stringlist) return [float(g.group(i)) for i in range(1,4)] for i in ["kpath_name", "kpath"]: d['stored_data'][i] = launch_doc['action']['stored_data'][i] kpoints_doc = d['stored_data']['kpath']['kpoints'] for i in kpoints_doc: kpoints_doc[i]=string_to_numlist(kpoints_doc[i]) bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=True) else: bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=False) bs_json = json.dumps(bs.to_dict) fs = gridfs.GridFS(db, "band_structure_fs") bs_id = fs.put(bs_json) d['calculations'][0]["band_structure_fs_id"] = bs_id coll.update({"dir_name": d["dir_name"]}, d, upsert=True) return d["task_id"], d else: logger.info("Skipping duplicate {}".format(d["dir_name"])) return result["task_id"], result else: d["task_id"] = 0 logger.info("Simulated insert into database for {} with task_id {}" .format(d["dir_name"], d["task_id"])) return 0, d
def assimilate(self, path, launches_coll=None): """ Parses vasp runs. Then insert the result into the db. and return the task_id or doc of the insertion. Returns: If in simulate_mode, the entire doc is returned for debugging purposes. Else, only the task_id of the inserted doc is returned. """ d = self.get_task_doc(path) if self.additional_fields: d.update(self.additional_fields) # always add additional fields, even for failed jobs try: d["dir_name_full"] = d["dir_name"].split(":")[1] d["dir_name"] = get_block_part(d["dir_name_full"]) d["stored_data"] = {} except: print 'COULD NOT GET DIR NAME' pprint.pprint(d) print traceback.format_exc() raise ValueError('IMPROPER PARSING OF {}'.format(path)) if not self.simulate: # Perform actual insertion into db. Because db connections cannot # be pickled, every insertion needs to create a new connection # to the db. conn = MongoClient(self.host, self.port) db = conn[self.database] if self.user: db.authenticate(self.user, self.password) coll = db[self.collection] # Insert dos data into gridfs and then remove it from the dict. # DOS data tends to be above the 4Mb limit for mongo docs. A ref # to the dos file is in the dos_fs_id. result = coll.find_one({"dir_name": d["dir_name"]}) if result is None or self.update_duplicates: if self.parse_dos and "calculations" in d: for calc in d["calculations"]: if "dos" in calc: dos = json.dumps(calc["dos"], cls=MontyEncoder) fs = gridfs.GridFS(db, "dos_fs") dosid = fs.put(dos) calc["dos_fs_id"] = dosid del calc["dos"] d["last_updated"] = datetime.datetime.today() if result is None: if ("task_id" not in d) or (not d["task_id"]): d["task_id"] = "mp-{}".format( db.counter.find_and_modify( query={"_id": "taskid"}, update={"$inc": {"c": 1}})["c"]) logger.info("Inserting {} with taskid = {}" .format(d["dir_name"], d["task_id"])) elif self.update_duplicates: d["task_id"] = result["task_id"] logger.info("Updating {} with taskid = {}" .format(d["dir_name"], d["task_id"])) #Fireworks processing self.process_fw(path, d) try: #Add oxide_type struct=Structure.from_dict(d["output"]["crystal"]) d["oxide_type"]=oxide_type(struct) except: logger.error("can't get oxide_type for {}".format(d["task_id"])) d["oxide_type"] = None #Override incorrect outcar subdocs for two step relaxations if "optimize structure" in d['task_type'] and \ os.path.exists(os.path.join(path, "relax2")): try: run_stats = {} for i in [1,2]: o_path = os.path.join(path,"relax"+str(i),"OUTCAR") o_path = o_path if os.path.exists(o_path) else o_path+".gz" outcar = Outcar(o_path) d["calculations"][i-1]["output"]["outcar"] = outcar.as_dict() run_stats["relax"+str(i)] = outcar.run_stats except: logger.error("Bad OUTCAR for {}.".format(path)) try: overall_run_stats = {} for key in ["Total CPU time used (sec)", "User time (sec)", "System time (sec)", "Elapsed time (sec)"]: overall_run_stats[key] = sum([v[key] for v in run_stats.values()]) run_stats["overall"] = overall_run_stats except: logger.error("Bad run stats for {}.".format(path)) d["run_stats"] = run_stats # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = d["pseudo_potential"]["functional"] labels = d["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = {"run_type": d["run_type"], "is_hubbard": d["is_hubbard"], "hubbards": d["hubbards"], "potcar_symbols": symbols} entry = ComputedEntry(Composition(d["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=d["task_id"]) d['is_compatible'] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility' d['is_compatible'] = None #task_type dependent processing if 'static' in d['task_type']: launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) for i in ["conventional_standard_structure", "symmetry_operations", "symmetry_dataset", "refined_structure"]: try: d['stored_data'][i] = launch_doc['action']['stored_data'][i] except: pass #parse band structure if necessary if ('band structure' in d['task_type'] or "Uniform" in d['task_type'])\ and d['state'] == 'successful': launch_doc = launches_coll.find_one({"fw_id": d['fw_id'], "launch_dir": {"$regex": d["dir_name"]}}, {"action.stored_data": 1}) vasp_run = Vasprun(zpath(os.path.join(path, "vasprun.xml")), parse_projected_eigen=False) if 'band structure' in d['task_type']: def string_to_numlist(stringlist): g=re.search('([0-9\-\.eE]+)\s+([0-9\-\.eE]+)\s+([0-9\-\.eE]+)', stringlist) return [float(g.group(i)) for i in range(1,4)] for i in ["kpath_name", "kpath"]: d['stored_data'][i] = launch_doc['action']['stored_data'][i] kpoints_doc = d['stored_data']['kpath']['kpoints'] for i in kpoints_doc: kpoints_doc[i]=string_to_numlist(kpoints_doc[i]) bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=True) else: bs=vasp_run.get_band_structure(efermi=d['calculations'][0]['output']['outcar']['efermi'], line_mode=False) bs_json = json.dumps(bs.as_dict(), cls=MontyEncoder) fs = gridfs.GridFS(db, "band_structure_fs") bs_id = fs.put(bs_json) d['calculations'][0]["band_structure_fs_id"] = bs_id # also override band gap in task doc gap = bs.get_band_gap() vbm = bs.get_vbm() cbm = bs.get_cbm() update_doc = {'bandgap': gap['energy'], 'vbm': vbm['energy'], 'cbm': cbm['energy'], 'is_gap_direct': gap['direct']} d['analysis'].update(update_doc) d['calculations'][0]['output'].update(update_doc) coll.update({"dir_name": d["dir_name"]}, d, upsert=True) return d["task_id"], d else: logger.info("Skipping duplicate {}".format(d["dir_name"])) return result["task_id"], result else: d["task_id"] = 0 logger.info("Simulated insert into database for {} with task_id {}" .format(d["dir_name"], d["task_id"])) return 0, d
def main(): """ Main routine """ parser = argparse.ArgumentParser(description='Calculate the band structure of a vasp calculation.') parser.add_argument('-d', '--density', nargs='?', default=10, type=int, help='k-point density of the bands (default: 10)') parser.add_argument('-s', '--sigma', nargs='?', default=0.04, type=float, help='SIGMA value in eV (default: 0.04)') parser.add_argument('-l', '--linemode', nargs='?', default=None, type=str, help='linemode file') parser.add_argument('-v', '--vasp', nargs='?', default='vasp', type=str, help='vasp executable') args = parser.parse_args() line_density = args.density line_file = args.linemode # Check that required files exist _check('vasprun.xml') _check('INCAR') _check('POSCAR') _check('POTCAR') _check('CHGCAR') # Get IBZ from vasprun vasprun = Vasprun('vasprun.xml') ibz = HighSymmKpath(vasprun.final_structure) # Create a temp directory print('Create temporary directory ... ', end='') tempdir = mkdtemp() print(tempdir) # Edit the inputs print('Saving new inputs in temporary directory ... ') incar = Incar.from_file('INCAR') print('Making the following changes to the INCAR:') print(' ICHARG = 11') print(' ISMEAR = 0') print(' SIGMA = %f' % args.sigma) incar['ICHARG'] = 11 # Constant density incar['ISMEAR'] = 0 # Gaussian Smearing incar['SIGMA'] = args.sigma # Smearing temperature incar.write_file(os.path.join(tempdir, 'INCAR')) # Generate line-mode kpoint file if line_file is None: print('Creating a new KPOINTS file:') kpoints = _automatic_kpoints(line_density, ibz) kpoints.write_file(os.path.join(tempdir, 'KPOINTS')) print('### BEGIN KPOINTS') print(kpoints) print('### END KPOINTS') else: cp(line_file, os.path.join(tempdir, 'KPOINTS')) # Copy other files (May take some time...) print('Copying POSCAR, POTCAR and CHGCAR to the temporary directory.') cp('POSCAR', os.path.join(tempdir, 'POSCAR')) cp('POTCAR', os.path.join(tempdir, 'POTCAR')) cp('CHGCAR', os.path.join(tempdir, 'CHGCAR')) # cd to temp directory and run vasp path = os.getcwd() os.chdir(tempdir) print('Running VASP in the temporary directory ...') try: check_call(args.vasp) except CalledProcessError: print('There was an error running VASP') _clean_exit(path, tempdir) # Read output vasprun = Vasprun('vasprun.xml') ibz = HighSymmKpath(vasprun.final_structure) _, _ = ibz.get_kpoints(line_density) bands = vasprun.get_band_structure() print('Success! Efermi = %f' % bands.efermi) # Backup vasprun.xml only print('Making a gzip backup of vasprun.xml called bands_vasprun.xml.gz') zfile = os.path.join(path, 'bands_vasprun.xml.gz') try: with gzip.open(zfile, 'wb') as gz, open('vasprun.xml', 'rb') as vr: gz.writelines(vr) except (OSError, IOError): print('There was an error with gzip') _clean_exit(path, tempdir) # Return to original path os.chdir(path) # Write band structure # There may be multiple bands due to spin or noncollinear. for key, item in bands.bands.items(): print('Preparing bands_%s.csv' % key) kpts = [] # Get list of kpoints for kpt in bands.kpoints: kpts.append(kpt.cart_coords) # Subtract fermi energy print('Shifting energies so Efermi = 0.') band = numpy.array(item) - bands.efermi # Prepend kpoint vector as label out = numpy.hstack([kpts, band.T]) final = [] lastrow = float('inf') * numpy.ones(3) for row in out: if numpy.linalg.norm(row[:3] - lastrow) > 1.e-12: final.append(row) lastrow = row[:3] # Write bands to csv file. print('Writing bands_%s.csv to disk' % key) with open('bands_%s.csv' % key, 'w+') as f: numpy.savetxt(f, numpy.array(final), delimiter=',', header=' kptx, kpty, kptz, band1, band2, ... ') # Delete temporary directory _clean_exit(path, tempdir, 0)