def test_all_methods(self):
        # create scratch directory with files....
        # having to do it all at once to minimize amount of time copying over to Scratch Directory
        with ScratchDir("."):
            # setup with fake Locpot object copied over
            copyfile( os.path.join(file_loc, "test_path_files.tar.gz"), "./test_path_files.tar.gz")
            tar = tarfile.open("test_path_files.tar.gz")
            tar.extractall()
            tar.close()
            blocpot = Locpot.from_file( os.path.join( file_loc, "bLOCPOT.gz"))
            blocpot.write_file("test_path_files/bulk/LOCPOT")
            dlocpot = Locpot.from_file( os.path.join( file_loc, "dLOCPOT.gz"))
            dlocpot.write_file("test_path_files/sub_1_Sb_on_Ga/charge_2/LOCPOT")

            # test_from_path
            sdp = SingleDefectParser.from_paths("test_path_files/sub_1_Sb_on_Ga/charge_2/",
                                                "test_path_files/bulk/", 18.12, 2)
            self.assertIsInstance(sdp, SingleDefectParser)
            self.assertIsInstance(sdp.defect_entry.defect, Substitution)
            self.assertEqual(sdp.defect_entry.parameters["bulk_path"],
                             "test_path_files/bulk/")
            self.assertEqual(sdp.defect_entry.parameters["defect_path"],
                             "test_path_files/sub_1_Sb_on_Ga/charge_2/")

            # test_freysoldt_loader
            for param_key in ["axis_grid", "bulk_planar_averages", "defect_planar_averages", \
                               "initial_defect_structure", "defect_frac_sc_coords"]:
                self.assertFalse(param_key in sdp.defect_entry.parameters.keys())
            bl = sdp.freysoldt_loader()
            self.assertIsInstance(bl, Locpot)
            for param_key in ["axis_grid", "bulk_planar_averages", "defect_planar_averages", \
                               "initial_defect_structure", "defect_frac_sc_coords"]:
                self.assertTrue(param_key in sdp.defect_entry.parameters.keys())

            # test_kumagai_loader
            for param_key in ["bulk_atomic_site_averages", "defect_atomic_site_averages", \
                              "site_matching_indices", "sampling_radius", "defect_index_sc_coords"]:
                self.assertFalse(param_key in sdp.defect_entry.parameters.keys())
            bo = sdp.kumagai_loader()
            for param_key in ["bulk_atomic_site_averages", "defect_atomic_site_averages", \
                              "site_matching_indices", "sampling_radius", "defect_index_sc_coords"]:
                self.assertTrue(param_key in sdp.defect_entry.parameters.keys())

            # test_get_stdrd_metadata
            sdp.get_stdrd_metadata()
            for param_key in ["eigenvalues", "kpoint_weights", "bulk_energy", \
                              "final_defect_structure", "defect_energy", "run_metadata"]:
                self.assertTrue(param_key in sdp.defect_entry.parameters.keys())

            # test_get_bulk_gap_data
            sdp.get_bulk_gap_data()
            self.assertEqual(sdp.defect_entry.parameters["mpid"], "mp-2534")
            self.assertAlmostEqual(sdp.defect_entry.parameters["gap"], 0.1887)

            # test_run_compatibility
            self.assertFalse('is_compatible' in sdp.defect_entry.parameters)
            sdp.run_compatibility()
            self.assertTrue('is_compatible' in sdp.defect_entry.parameters)
Example #2
0
def chg_locp_average():
   chg=False
   print("which file would like to average: CHG or LOCPOT ?")
   wait_sep()
   in_str=""
   while in_str=="":
         in_str=input().strip()
   if in_str.lower()=='chg':
      filename='CHG'
      check_file(filename)
      grid_data = CHGCAR.from_file(filename)
      head_line="#%(key1)+s %(key2)+s"%{'key1':'Distance/Ang','key2':'Average Charge/(e/Ang**3)'}
      chg=True
   elif in_str.lower()=='locpot':
      filename='LOCPOT'
      check_file(filename)
      grid_data = Locpot.from_file(filename)
      head_line="#%(key1)+s %(key2)+s"%{'key1':'Distance/Ang','key2':'Average Potential/(eV)'}
   else:
      print('unknown file file: '+in_str)
      os._exit()

   step_count=1
   check_file(filename)
   proc_str="Reading Data From "+ filename +" File ..."
   procs(proc_str,step_count,sp='-->>')
   volume=grid_data.structure.volume 
   print("which direction would like to average: x y or z ?")
   wait_sep()
   in_str=""
   while in_str=="":
      in_str=input().strip().lower()
   if in_str=="x":
      selected_dir=0
   elif in_str=='y':
      selected_dir=1
   elif in_str=='z':
      selected_dir=2
   else:
       print("Unknow Direction!")
       return

   axis_grid=grid_data.get_axis_grid(selected_dir)
   if chg:
      aver_grid=grid_data.get_average_along_axis(selected_dir)/volume
   else:
      aver_grid=grid_data.get_average_along_axis(selected_dir)

   data=np.vstack((axis_grid,aver_grid)).T

   step_count+=1
   if chg:
      filename="average_CHG_"+in_str+'.dat'
   else:
      filename="average_LOCPOT_"+in_str+'.dat'

   proc_str="Writting Average Data to "+ filename +" File ..."
   procs(proc_str,step_count,sp='-->>')
   write_col_data(filename,data,head_line)
Example #3
0
    def test_freysoldt_and_kumagai(self):
        with ScratchDir("."):
            # setup with fake Locpot object copied over
            copyfile(os.path.join(TEST_DIR, "test_path_files.tar.gz"),
                     "test_path_files.tar.gz")
            tar = tarfile.open("test_path_files.tar.gz")
            tar.extractall()
            tar.close()
            blocpot = Locpot.from_file(os.path.join(TEST_DIR, "bLOCPOT.gz"))
            blocpot.write_file(
                os.path.join("test_path_files", "bulk", "LOCPOT"))
            dlocpot = Locpot.from_file(os.path.join(TEST_DIR, "dLOCPOT.gz"))
            dlocpot.write_file(
                os.path.join("test_path_files", "sub_1_Sb_on_Ga", "charge_2",
                             "LOCPOT"))

            fcc = freysoldt_correction_from_paths(
                os.path.join("test_path_files", "sub_1_Sb_on_Ga", "charge_2"),
                os.path.join("test_path_files", "bulk"),
                18.12,
                2,
                plot=True)
            self.assertAlmostEqual(fcc, -1.2435280589593547)
            self.assertTrue(
                os.path.exists(
                    os.path.join(
                        "test_path_files", "sub_1_Sb_on_Ga", "charge_2",
                        "Sub_Sb_on_Ga_mult32_chg_2_axis1_freysoldtplot.pdf")))

            kcc = kumagai_correction_from_paths(
                os.path.join("test_path_files", "sub_1_Sb_on_Ga", "charge_2"),
                os.path.join("test_path_files", "bulk"),
                18.12,
                2,
                plot=True)
            self.assertAlmostEqual(kcc, 0.6387768530616106)
            self.assertTrue(
                os.path.exists(
                    os.path.join("test_path_files", "sub_1_Sb_on_Ga",
                                 "charge_2",
                                 "Sub_Sb_on_Ga_mult32_chg_2_kumagaiplot.pdf")))
Example #4
0
    def test_freysoldt_and_kumagai(self):
        # create scratch directory with files....
        # having to do it all at once to minimize amount of time copying over to Scratch Directory
        with ScratchDir("."):
            # setup with fake Locpot object copied over
            copyfile(os.path.join(file_loc, "test_path_files.tar.gz"),
                     "./test_path_files.tar.gz")
            tar = tarfile.open("test_path_files.tar.gz")
            tar.extractall()
            tar.close()
            blocpot = Locpot.from_file(os.path.join(file_loc, "bLOCPOT.gz"))
            blocpot.write_file("test_path_files/bulk/LOCPOT")
            dlocpot = Locpot.from_file(os.path.join(file_loc, "dLOCPOT.gz"))
            dlocpot.write_file(
                "test_path_files/sub_1_Sb_on_Ga/charge_2/LOCPOT")

            fcc = freysoldt_correction_from_paths(
                "test_path_files/sub_1_Sb_on_Ga/charge_2/",
                "test_path_files/bulk/",
                18.12,
                2,
                plot=True)
            self.assertEqual(fcc, -1.2435280589593547)
            self.assertTrue(
                os.path.exists(
                    "test_path_files/sub_1_Sb_on_Ga/charge_2/Sub_Sb_on_Ga_mult32_chg_2_axis1_freysoldtplot.pdf"
                ))

            kcc = kumagai_correction_from_paths(
                "test_path_files/sub_1_Sb_on_Ga/charge_2/",
                "test_path_files/bulk/",
                18.12,
                2,
                plot=True)
            self.assertEqual(kcc, 0.6387768530616106)
            self.assertTrue(
                os.path.exists(
                    "test_path_files/sub_1_Sb_on_Ga/charge_2/Sub_Sb_on_Ga_mult32_chg_2_kumagaiplot.pdf"
                ))
Example #5
0
    def process_vasprun(self, dir_name, taskname, filename):
        """
        Adapted from matgendb.creator

        Process a vasprun.xml file.
        """
        vasprun_file = os.path.join(dir_name, filename)

        vrun = Vasprun(vasprun_file)

        d = vrun.as_dict()

        # rename formula keys
        for k, v in {"formula_pretty": "pretty_formula",
                     "composition_reduced": "reduced_cell_formula",
                     "composition_unit_cell": "unit_cell_formula"}.items():
            d[k] = d.pop(v)

        for k in ["eigenvalues", "projected_eigenvalues"]:  # large storage space breaks some docs
            if k in d["output"]:
                del d["output"][k]

        comp = Composition(d["composition_unit_cell"])
        d["formula_anonymous"] = comp.anonymized_formula
        d["formula_reduced_abc"] = comp.reduced_composition.alphabetical_formula
        d["dir_name"] = os.path.abspath(dir_name)
        d["completed_at"] = str(datetime.datetime.fromtimestamp(os.path.getmtime(vasprun_file)))
        d["density"] = vrun.final_structure.density

        # replace 'crystal' with 'structure'
        d["input"]["structure"] = d["input"].pop("crystal")
        d["output"]["structure"] = d["output"].pop("crystal")
        for k, v in {"energy": "final_energy", "energy_per_atom": "final_energy_per_atom"}.items():
            d["output"][k] = d["output"].pop(v)

        if self.parse_dos == True or (str(self.parse_dos).lower() == "auto" and vrun.incar.get("NSW", 1) == 0):
            try:
                d["dos"] = vrun.complete_dos.as_dict()
            except:
                raise ValueError("No valid dos data exist in {}.".format(dir_name))

        # Band structure parsing logic
        if str(self.bandstructure_mode).lower() == "auto":
            # if line mode nscf
            if vrun.incar.get("ICHARG", 0) > 10 and vrun.kpoints.num_kpts > 0:
                bs_vrun = BSVasprun(vasprun_file, parse_projected_eigen=True)
                bs = bs_vrun.get_band_structure(line_mode=True)
            # else if nscf
            elif vrun.incar.get("ICHARG", 0) > 10:
                bs_vrun = BSVasprun(vasprun_file, parse_projected_eigen=True)
                bs = bs_vrun.get_band_structure()
            # else just regular calculation
            else:
                bs = vrun.get_band_structure()

            # only save the bandstructure if not moving ions
            if vrun.incar["NSW"] == 0:
                d["bandstructure"] = bs.as_dict()
        # legacy line/True behavior for bandstructure_mode
        elif self.bandstructure_mode:
            bs_vrun = BSVasprun(vasprun_file, parse_projected_eigen=True)
            bs = bs_vrun.get_band_structure(line_mode=(str(self.bandstructure_mode).lower() == "line"))
            d["bandstructure"] = bs.as_dict()
        # parse bandstructure for vbm/cbm/bandgap but don't save
        else:
            bs = vrun.get_band_structure()

        # Parse electronic information if possible.
        # For certain optimizers this is broken and we don't get an efermi resulting in the bandstructure
        try:
            bs_gap = bs.get_band_gap()
            d["output"]["vbm"] = bs.get_vbm()["energy"]
            d["output"]["cbm"] = bs.get_cbm()["energy"]
            d["output"]["bandgap"] = bs_gap["energy"]
            d["output"]["is_gap_direct"] = bs_gap["direct"]
            d["output"]["is_metal"] = bs.is_metal()
            if not bs_gap["direct"]:
                d["output"]["direct_gap"] = bs.get_direct_band_gap()
            if isinstance(bs, BandStructureSymmLine):
                d["output"]["transition"] = bs_gap["transition"]

        except Exception:
            if self.bandstructure_mode is True:
                import traceback
                logger.error(traceback.format_exc())
                logger.error("Error in " + os.path.abspath(dir_name) + ".\n" + traceback.format_exc())
                raise
            logger.warning("Error in parsing bandstructure")
            if vrun.incar["IBRION"] == 1:
                logger.warning("Vasp doesn't properly output efermi for IBRION == 1")

        d["task"] = {"type": taskname, "name": taskname}

        d["output_file_paths"] = self.process_raw_data(dir_name, taskname=taskname)

        if "locpot" in d["output_file_paths"] and self.parse_locpot:
            locpot = Locpot.from_file(os.path.join(dir_name, d["output_file_paths"]["locpot"]))
            d["output"]["locpot"] = {i: locpot.get_average_along_axis(i) for i in range(3)}

        if hasattr(vrun, "force_constants"):
            # phonon-dfpt
            d["output"]["force_constants"] = vrun.force_constants.tolist()
            d["output"]["normalmode_eigenvals"] = vrun.normalmode_eigenvals.tolist()
            d["output"]["normalmode_eigenvecs"] = vrun.normalmode_eigenvecs.tolist()
        return d
Example #6
0
    def process_vasprun(self, dir_name, taskname, filename):
        """
        Adapted from matgendb.creator

        Process a vasprun.xml file.
        """
        vasprun_file = os.path.join(dir_name, filename)

        vrun = Vasprun(vasprun_file, parse_potcar_file=self.parse_potcar_file)

        d = vrun.as_dict()

        # rename formula keys
        for k, v in {
                "formula_pretty": "pretty_formula",
                "composition_reduced": "reduced_cell_formula",
                "composition_unit_cell": "unit_cell_formula"
        }.items():
            d[k] = d.pop(v)

        for k in ["eigenvalues", "projected_eigenvalues"
                  ]:  # large storage space breaks some docs
            if k in d["output"]:
                del d["output"][k]

        comp = Composition(d["composition_unit_cell"])
        d["formula_anonymous"] = comp.anonymized_formula
        d["formula_reduced_abc"] = comp.reduced_composition.alphabetical_formula
        d["dir_name"] = os.path.abspath(dir_name)
        d["completed_at"] = str(
            datetime.datetime.fromtimestamp(os.path.getmtime(vasprun_file)))
        d["density"] = vrun.final_structure.density

        # replace 'crystal' with 'structure'
        d["input"]["structure"] = d["input"].pop("crystal")
        d["output"]["structure"] = d["output"].pop("crystal")
        for k, v in {
                "energy": "final_energy",
                "energy_per_atom": "final_energy_per_atom"
        }.items():
            d["output"][k] = d["output"].pop(v)

        # Process bandstructure and DOS
        if self.bandstructure_mode != False:
            bs = self.process_bandstructure(vrun)
            if bs:
                d["bandstructure"] = bs

        if self.parse_dos != False:
            dos = self.process_dos(vrun)
            if dos:
                d["dos"] = dos

        # Parse electronic information if possible.
        # For certain optimizers this is broken and we don't get an efermi resulting in the bandstructure
        try:
            bs = vrun.get_band_structure()
            bs_gap = bs.get_band_gap()
            d["output"]["vbm"] = bs.get_vbm()["energy"]
            d["output"]["cbm"] = bs.get_cbm()["energy"]
            d["output"]["bandgap"] = bs_gap["energy"]
            d["output"]["is_gap_direct"] = bs_gap["direct"]
            d["output"]["is_metal"] = bs.is_metal()
            if not bs_gap["direct"]:
                d["output"]["direct_gap"] = bs.get_direct_band_gap()
            if isinstance(bs, BandStructureSymmLine):
                d["output"]["transition"] = bs_gap["transition"]

        except Exception:
            logger.warning("Error in parsing bandstructure")
            if vrun.incar["IBRION"] == 1:
                logger.warning(
                    "Vasp doesn't properly output efermi for IBRION == 1")
            if self.bandstructure_mode is True:
                logger.error(traceback.format_exc())
                logger.error("Error in " + os.path.abspath(dir_name) + ".\n" +
                             traceback.format_exc())
                raise

        # Should roughly agree with information from .get_band_structure() above, subject to tolerances
        # If there is disagreement, it may be related to VASP incorrectly assigning the Fermi level
        try:
            band_props = vrun.eigenvalue_band_properties
            d["output"]["eigenvalue_band_properties"] = {
                "bandgap": band_props[0],
                "cbm": band_props[1],
                "vbm": band_props[2],
                "is_gap_direct": band_props[3]
            }
        except Exception:
            logger.warning("Error in parsing eigenvalue band properties")

        # store run name and location ,e.g. relax1, relax2, etc.
        d["task"] = {"type": taskname, "name": taskname}

        # include output file names
        d["output_file_paths"] = self.process_raw_data(dir_name,
                                                       taskname=taskname)

        # parse axially averaged locpot
        if "locpot" in d["output_file_paths"] and self.parse_locpot:
            locpot = Locpot.from_file(
                os.path.join(dir_name, d["output_file_paths"]["locpot"]))
            d["output"]["locpot"] = {
                i: locpot.get_average_along_axis(i)
                for i in range(3)
            }

        if self.store_volumetric_data:
            for file in self.store_volumetric_data:
                if file in d["output_file_paths"]:
                    try:
                        # assume volumetric data is all in CHGCAR format
                        data = Chgcar.from_file(
                            os.path.join(dir_name,
                                         d["output_file_paths"][file]))
                        d[file] = data.as_dict()
                    except:
                        raise ValueError("Failed to parse {} at {}.".format(
                            file, d["output_file_paths"][file]))

        # parse force constants
        if hasattr(vrun, "force_constants"):
            d["output"]["force_constants"] = vrun.force_constants.tolist()
            d["output"][
                "normalmode_eigenvals"] = vrun.normalmode_eigenvals.tolist()
            d["output"][
                "normalmode_eigenvecs"] = vrun.normalmode_eigenvecs.tolist()

        # perform Bader analysis using Henkelman bader
        if self.parse_bader and "chgcar" in d["output_file_paths"]:
            suffix = '' if taskname == 'standard' else ".{}".format(taskname)
            bader = bader_analysis_from_path(dir_name, suffix=suffix)
            d["bader"] = bader

        return d
Example #7
0
#%%
from matplotlib import cm
import numpy as np
from pymatgen.core.sites import Site
from pymatgen.io.vasp import Locpot
import matplotlib.pyplot as plt
import os

os.chdir('/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/vasp/my015/4/lvhar')
loc = Locpot.from_file('LOCPOT')
os.chdir('/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/vasp/my015/from-gulp/421/locpot')
# os.chdir('/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/vasp/my015/from-gulp/421/opti/loc')
loc2 = Locpot.from_file('LOCPOT')
os.chdir('/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/vasp/stengel/015/4/lvhar')
loc3 = Locpot.from_file('LOCPOT')
tloc = [loc, loc2, loc3]
# tloc = [loc, loc2]

#%%
def charge(pot):
    dat = np.sum(pot.data['total'], axis=0) / pot.dim[0]
    dat = np.roll(dat, int(pot.dim[1] * 0.8) // 2, axis=0)
    dat = np.swapaxes(dat, 0, 1)
    grad = np.gradient(dat)
    u = grad[0]
    v = grad[1]
    uu = np.gradient(u)
    vv = np.gradient(v)
    return(uu, vv)

u, v = charge(loc)
Example #8
0
#%%
import matplotlib.pyplot as plt
from pymatgen.core.sites import Site
from pymatgen.io.vasp import Locpot
import os

os.chdir(
    '/home/jinho93/new/oxides/perobskite/lanthanum-aluminate/periodic_step/vasp/stengel/015/4/lvhar'
)

loc = Locpot.from_file('LOCPOT')

s = loc.structure

from scipy.interpolate import griddata
import numpy as np
#%%

dat = loc.data['total']
x = []
y = []
z = []
site: Site
on = False
for site in sorted(s.sites, key=lambda x: x.c):
    if site.species_string == "O":
        # or site.species_string == "Al":
        x.append(site.b)
        y.append(site.c)
        z.append(dat[int(dat.shape[0] * site.a),
                     int(dat.shape[1] * site.b),
Example #9
0
    def process_vasprun(self, dir_name, taskname, filename):
        """
        Adapted from matgendb.creator

        Process a vasprun.xml file.
        """
        vasprun_file = os.path.join(dir_name, filename)

        vrun = Vasprun(vasprun_file)

        d = vrun.as_dict()

        # rename formula keys
        for k, v in {"formula_pretty": "pretty_formula",
                     "composition_reduced": "reduced_cell_formula",
                     "composition_unit_cell": "unit_cell_formula"}.items():
            d[k] = d.pop(v)

        for k in ["eigenvalues", "projected_eigenvalues"]:  # large storage space breaks some docs
            if k in d["output"]:
                del d["output"][k]

        comp = Composition(d["composition_unit_cell"])
        d["formula_anonymous"] = comp.anonymized_formula
        d["formula_reduced_abc"] = comp.reduced_composition.alphabetical_formula
        d["dir_name"] = os.path.abspath(dir_name)
        d["completed_at"] = str(datetime.datetime.fromtimestamp(os.path.getmtime(vasprun_file)))
        d["density"] = vrun.final_structure.density

        # replace 'crystal' with 'structure'
        d["input"]["structure"] = d["input"].pop("crystal")
        d["output"]["structure"] = d["output"].pop("crystal")
        for k, v in {"energy": "final_energy", "energy_per_atom": "final_energy_per_atom"}.items():
            d["output"][k] = d["output"].pop(v)

        # Process bandstructure and DOS
        if self.bandstructure_mode != False:
            bs = self.process_bandstructure(vrun)
            if bs:
                d["bandstructure"] = bs

        if self.parse_dos != False:
            dos = self.process_dos(vrun)
            if dos:
                d["dos"] = dos

        # Parse electronic information if possible.
        # For certain optimizers this is broken and we don't get an efermi resulting in the bandstructure
        try:
            bs = vrun.get_band_structure()
            bs_gap = bs.get_band_gap()
            d["output"]["vbm"] = bs.get_vbm()["energy"]
            d["output"]["cbm"] = bs.get_cbm()["energy"]
            d["output"]["bandgap"] = bs_gap["energy"]
            d["output"]["is_gap_direct"] = bs_gap["direct"]
            d["output"]["is_metal"] = bs.is_metal()
            if not bs_gap["direct"]:
                d["output"]["direct_gap"] = bs.get_direct_band_gap()
            if isinstance(bs, BandStructureSymmLine):
                d["output"]["transition"] = bs_gap["transition"]

        except Exception:
            logger.warning("Error in parsing bandstructure")
            if vrun.incar["IBRION"] == 1:
                logger.warning("Vasp doesn't properly output efermi for IBRION == 1")
            if self.bandstructure_mode is True:
                logger.error(traceback.format_exc())
                logger.error("Error in " + os.path.abspath(dir_name) + ".\n" + traceback.format_exc())
                raise

        # store run name and location ,e.g. relax1, relax2, etc.
        d["task"] = {"type": taskname, "name": taskname}

        # include output file names
        d["output_file_paths"] = self.process_raw_data(dir_name, taskname=taskname)

        # parse axially averaged locpot
        if "locpot" in d["output_file_paths"] and self.parse_locpot:
            locpot = Locpot.from_file(os.path.join(dir_name, d["output_file_paths"]["locpot"]))
            d["output"]["locpot"] = {i: locpot.get_average_along_axis(i) for i in range(3)}

        if self.parse_chgcar != False:
            # parse CHGCAR file only for static calculations
            # TODO require static run later
            # if self.parse_chgcar == True and vrun.incar.get("NSW", 0) < 1:
            try:
                chgcar = self.process_chgcar(os.path.join(dir_name, d["output_file_paths"]["chgcar"]))
            except:
                raise ValueError("No valid charge data exist")
            d["chgcar"] = chgcar

        if self.parse_aeccar != False:
            try:
                chgcar = self.process_chgcar(os.path.join(dir_name, d["output_file_paths"]["aeccar0"]))
            except:
                raise ValueError("No valid charge data exist")
            d["aeccar0"] = chgcar
            try:
                chgcar = self.process_chgcar(os.path.join(dir_name, d["output_file_paths"]["aeccar2"]))
            except:
                raise ValueError("No valid charge data exist")
            d["aeccar2"] = chgcar

        # parse force constants
        if hasattr(vrun, "force_constants"):
            d["output"]["force_constants"] = vrun.force_constants.tolist()
            d["output"]["normalmode_eigenvals"] = vrun.normalmode_eigenvals.tolist()
            d["output"]["normalmode_eigenvecs"] = vrun.normalmode_eigenvecs.tolist()

        # Try and perform bader
        if self.parse_bader:
            try:
                bader = bader_analysis_from_path(dir_name, suffix=".{}".format(taskname))
            except Exception as e:
                bader = "Bader analysis failed: {}".format(e)
            d["bader"] = bader

        return d