Ejemplo n.º 1
0
 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
Ejemplo n.º 2
0
 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")
Ejemplo n.º 3
0
 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")
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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')
Ejemplo n.º 7
0
__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)
Ejemplo n.º 8
0
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)
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
    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")
Ejemplo n.º 12
0
    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
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
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)