Exemple #1
0
    def from_path(cls, path, suffix="", zpsp=None):
        """
        Convenience method to run critic2 analysis on a folder containing
        typical VASP output files.
        This method will:

        1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
        counterparts.

        2. If AECCAR* files are present, constructs a temporary reference
        file as AECCAR0 + AECCAR2.

        3. Runs critic2 analysis twice: once for charge, and a second time
        for the charge difference (magnetization density).

        :param path: path to folder to search in
        :param suffix: specific suffix to look for (e.g. '.relax1' for
            'CHGCAR.relax1.gz')
        :param zpsp: manually specify ZPSP if POTCAR not present
        :return:
        """

        chgcar_path = get_filepath("CHGCAR", "Could not find CHGCAR!", path, suffix)
        chgcar = Chgcar.from_file(chgcar_path)
        chgcar_ref = None

        if not zpsp:

            potcar_path = get_filepath(
                "POTCAR",
                "Could not find POTCAR, will not be able to calculate charge transfer.",
                path,
                suffix,
            )

            if potcar_path:
                potcar = Potcar.from_file(potcar_path)
                zpsp = {p.element: p.zval for p in potcar}

        if not zpsp:
            # try and get reference "all-electron-like" charge density if zpsp not present
            aeccar0_path = get_filepath(
                "AECCAR0",
                "Could not find AECCAR0, interpret Bader results with caution.",
                path,
                suffix,
            )
            aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

            aeccar2_path = get_filepath(
                "AECCAR2",
                "Could not find AECCAR2, interpret Bader results with caution.",
                path,
                suffix,
            )
            aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

            chgcar_ref = aeccar0.linear_add(aeccar2) if (aeccar0 and aeccar2) else None

        return cls(chgcar.structure, chgcar, chgcar_ref, zpsp=zpsp)
Exemple #2
0
    def test_writestate_ncl(self):
        print("TEST WRITE NCL")
        sys.stdout.flush()
        from pymatgen.io.vasp.outputs import Chgcar

        wf = NCLWavefunction.from_directory("noncollinear")
        fileprefix = ""
        b, k, s = 10, 1, 0
        state1, state2 = wf.write_state_realspace(b, k, s, fileprefix="")
        state1, state2 = wf.write_state_realspace(b,
                                                  k,
                                                  s,
                                                  fileprefix="",
                                                  dim=np.array([30, 30, 30]))
        assert state1.shape[0] == 30
        assert state1.shape[1] == 30
        assert state1.shape[2] == 30
        assert state1.dtype == np.complex128
        filename_base = "%sB%dK%dS%d" % (fileprefix, b, k, s)
        filename1 = "%s_UP_REAL.vasp" % filename_base
        filename2 = "%s_UP_IMAG.vasp" % filename_base
        filename3 = "%s_DOWN_REAL.vasp" % filename_base
        filename4 = "%s_DOWN_IMAG.vasp" % filename_base
        chg1 = Chgcar.from_file(filename1)
        chg2 = Chgcar.from_file(filename2)
        chg3 = Chgcar.from_file(filename3)
        chg4 = Chgcar.from_file(filename4)
        upart = chg1.data["total"]**2 + chg2.data["total"]**2
        dpart = chg3.data["total"]**2 + chg4.data["total"]**2
        vol = chg1.poscar.structure.volume
        assert_almost_equal(np.sum((upart + dpart) * vol / 30**3), 1, 2)
        os.remove(filename1)
        os.remove(filename2)
        os.remove(filename3)
        os.remove(filename4)
Exemple #3
0
    def test_soc_chgcar(self):

        filepath = os.path.join(test_dir, "CHGCAR.NiO_SOC.gz")
        chg = Chgcar.from_file(filepath)
        self.assertEqual(set(chg.data.keys()),
                         {'total', 'diff_x', 'diff_y', 'diff_z', 'diff'})
        self.assertTrue(chg.is_soc)
        self.assertEqual(chg.data['diff'].shape, chg.data['diff_y'].shape)

        # check our construction of chg.data['diff'] makes sense
        # this has been checked visually too and seems reasonable
        self.assertEqual(
            abs(chg.data['diff'][0][0][0]),
            np.linalg.norm([
                chg.data['diff_x'][0][0][0], chg.data['diff_y'][0][0][0],
                chg.data['diff_z'][0][0][0]
            ]))

        # and that the net magnetization is about zero
        # note: we get ~ 0.08 here, seems a little high compared to
        # vasp output, but might be due to chgcar limitations?
        self.assertAlmostEqual(chg.net_magnetization, 0.0, places=0)

        chg.write_file("CHGCAR_pmg_soc")
        chg_from_file = Chgcar.from_file("CHGCAR_pmg_soc")
        self.assertTrue(chg_from_file.is_soc)
        os.remove("CHGCAR_pmg_soc")
Exemple #4
0
    def from_path(cls, path, suffix=""):
        """
        Convenient constructor that takes in the path name of VASP run
        to perform Bader analysis.

        Args:
            path (str): Name of directory where VASP output files are
                stored.
            suffix (str): specific suffix to look for (e.g. '.relax1'
                for 'CHGCAR.relax1.gz').

        """
        def _get_filepath(filename):
            name_pattern = (filename + suffix +
                            "*" if filename != "POTCAR" else filename + "*")
            paths = glob.glob(os.path.join(path, name_pattern))
            fpath = None
            if len(paths) >= 1:
                # using reverse=True because, if multiple files are present,
                # they likely have suffixes 'static', 'relax', 'relax2', etc.
                # and this would give 'static' over 'relax2' over 'relax'
                # however, better to use 'suffix' kwarg to avoid this!
                paths.sort(reverse=True)
                warning_msg = ("Multiple files detected, using %s" %
                               os.path.basename(paths[0])
                               if len(paths) > 1 else None)
                fpath = paths[0]
            else:
                warning_msg = "Could not find %s" % filename
                if filename in ["AECCAR0", "AECCAR2"]:
                    warning_msg += ", cannot calculate charge transfer."
                elif filename == "POTCAR":
                    warning_msg += ", interpret Bader results with caution."
            if warning_msg:
                warnings.warn(warning_msg)
            return fpath

        chgcar_filename = _get_filepath("CHGCAR")
        if chgcar_filename is None:
            raise IOError("Could not find CHGCAR!")
        potcar_filename = _get_filepath("POTCAR")
        aeccar0 = _get_filepath("AECCAR0")
        aeccar2 = _get_filepath("AECCAR2")
        if aeccar0 and aeccar2:
            # `chgsum.pl AECCAR0 AECCAR2` equivalent to obtain chgref_file
            chgref = Chgcar.from_file(aeccar0) + Chgcar.from_file(aeccar2)
            chgref_filename = "CHGREF"
            chgref.write_file(chgref_filename)
        else:
            chgref_filename = None
        return cls(
            chgcar_filename=chgcar_filename,
            potcar_filename=potcar_filename,
            chgref_filename=chgref_filename,
        )
    def from_path(cls, path, suffix=''):
        """
        Convenience method to run critic2 analysis on a folder containing
        typical VASP output files.
        This method will:

        1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
        counterparts.

        2. If AECCAR* files are present, constructs a temporary reference
        file as AECCAR0 + AECCAR2.

        3. Runs critic2 analysis twice: once for charge, and a second time
        for the charge difference (magnetization density).

        :param path: path to folder to search in
        :param suffix: specific suffix to look for (e.g. '.relax1' for
            'CHGCAR.relax1.gz')
        :return:
        """
        def _get_filepath(filename, warning, path=path, suffix=suffix):
            paths = glob.glob(os.path.join(path, filename + suffix + '*'))
            if not paths:
                warnings.warn(warning)
                return None
            if len(paths) > 1:
                # using reverse=True because, if multiple files are present,
                # they likely have suffixes 'static', 'relax', 'relax2', etc.
                # and this would give 'static' over 'relax2' over 'relax'
                # however, better to use 'suffix' kwarg to avoid this!
                paths.sort(reverse=True)
                warnings.warn('Multiple files detected, using {}'.format(
                    os.path.basename(path)))
            path = paths[0]
            return path

        chgcar_path = _get_filepath('CHGCAR', 'Could not find CHGCAR!')
        chgcar = Chgcar.from_file(chgcar_path)

        aeccar0_path = _get_filepath(
            'AECCAR0',
            'Could not find AECCAR0, interpret Bader results with caution.')
        aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

        aeccar2_path = _get_filepath(
            'AECCAR2',
            'Could not find AECCAR2, interpret Bader results with caution.')
        aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

        chgcar_ref = aeccar0.linear_add(aeccar2) if (aeccar0
                                                     and aeccar2) else None

        return cls(chgcar.structure, chgcar, chgcar_ref)
Exemple #6
0
    def from_path(cls, path, suffix=""):
        """
        Convenient constructor that takes in the path name of VASP run
        to perform Bader analysis.

        Args:
            path (str): Name of directory where VASP output files are
                stored.
            suffix (str): specific suffix to look for (e.g. '.relax1'
                for 'CHGCAR.relax1.gz').

        """

        def _get_filepath(filename):
            name_pattern = filename + suffix + '*' if filename != 'POTCAR' \
                else filename + '*'
            paths = glob.glob(os.path.join(path, name_pattern))
            fpath = None
            if len(paths) >= 1:
                # using reverse=True because, if multiple files are present,
                # they likely have suffixes 'static', 'relax', 'relax2', etc.
                # and this would give 'static' over 'relax2' over 'relax'
                # however, better to use 'suffix' kwarg to avoid this!
                paths.sort(reverse=True)
                warning_msg = "Multiple files detected, using %s" \
                              % os.path.basename(paths[0]) if len(paths) > 1 \
                    else None
                fpath = paths[0]
            else:
                warning_msg = "Could not find %s" % filename
                if filename in ['AECCAR0', 'AECCAR2']:
                    warning_msg += ", cannot calculate charge transfer."
                elif filename == "POTCAR":
                    warning_msg += ", interpret Bader results with caution."
            if warning_msg:
                warnings.warn(warning_msg)
            return fpath

        chgcar_filename = _get_filepath("CHGCAR")
        if chgcar_filename is None:
            raise IOError("Could not find CHGCAR!")
        potcar_filename = _get_filepath("POTCAR")
        aeccar0 = _get_filepath("AECCAR0")
        aeccar2 = _get_filepath("AECCAR2")
        if (aeccar0 and aeccar2):
            # `chgsum.pl AECCAR0 AECCAR2` equivalent to obtain chgref_file
            chgref = Chgcar.from_file(aeccar0) + Chgcar.from_file(aeccar2)
            chgref_filename = "CHGREF"
            chgref.write_file(chgref_filename)
        else:
            chgref_filename = None
        return cls(chgcar_filename, potcar_filename=potcar_filename,
                   chgref_filename=chgref_filename)
Exemple #7
0
def bader_analysis_from_path(path, suffix=""):
    """
    Convenience method to run Bader analysis on a folder containing
    typical VASP output files.

    This method will:

    1. Look for files CHGCAR, AECCAR0, AECCAR2, POTCAR or their gzipped
    counterparts.
    2. If AECCAR* files are present, constructs a temporary reference
    file as AECCAR0 + AECCAR2
    3. Runs Bader analysis twice: once for charge, and a second time
    for the charge difference (magnetization density).

    :param path: path to folder to search in
    :param suffix: specific suffix to look for (e.g. '.relax1' for 'CHGCAR.relax1.gz'
    :return: summary dict
    """
    def _get_filepath(filename, warning, path=path, suffix=suffix):
        paths = glob.glob(os.path.join(path, filename + suffix + "*"))
        if not paths:
            warnings.warn(warning)
            return None
        if len(paths) > 1:
            # using reverse=True because, if multiple files are present,
            # they likely have suffixes 'static', 'relax', 'relax2', etc.
            # and this would give 'static' over 'relax2' over 'relax'
            # however, better to use 'suffix' kwarg to avoid this!
            paths.sort(reverse=True)
            warnings.warn(
                f"Multiple files detected, using {os.path.basename(path)}")
        path = paths[0]
        return path

    chgcar_path = _get_filepath("CHGCAR", "Could not find CHGCAR!")
    chgcar = Chgcar.from_file(chgcar_path)

    aeccar0_path = _get_filepath(
        "AECCAR0",
        "Could not find AECCAR0, interpret Bader results with caution.")
    aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

    aeccar2_path = _get_filepath(
        "AECCAR2",
        "Could not find AECCAR2, interpret Bader results with caution.")
    aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

    potcar_path = _get_filepath(
        "POTCAR", "Could not find POTCAR, cannot calculate charge transfer.")
    potcar = Potcar.from_file(potcar_path) if potcar_path else None

    return bader_analysis_from_objects(chgcar, potcar, aeccar0, aeccar2)
Exemple #8
0
 def setUp(self):
     # This is a CHGCAR_sum file with reduced grid size
     chgcar_path = os.path.join(test_dir, "CHGCAR.FePO4")
     chg_FePO4 = Chgcar.from_file(chgcar_path)
     self.chgcar_path = chgcar_path
     self.chg_FePO4 = chg_FePO4
     self.cia_FePO4 = ChargeInsertionAnalyzer(chg_FePO4)
Exemple #9
0
    def test_init(self):
        filepath = os.path.join(test_dir, "CHGCAR.nospin")
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 2)[0, 1], 0)
        filepath = os.path.join(test_dir, "CHGCAR.spin")
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1], -0.0043896932237534022)
        # test sum
        chg += chg
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1], -0.0043896932237534022 * 2)

        filepath = os.path.join(test_dir, "CHGCAR.Fe3O4")
        chg = Chgcar.from_file(filepath)
        ans = [1.93313368, 3.91201473, 4.11858277, 4.1240093, 4.10634989, 3.38864822]
        myans = chg.get_integrated_diff(0, 3, 6)
        self.assertTrue(np.allclose(myans[:, 1], ans))
Exemple #10
0
def bader_analysis_from_path(path, suffix=''):
    """
    Convenience method to run Bader analysis on a folder containing
    typical VASP output files.

    This method will:

    1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
    counterparts.
    2. If AECCAR* files are present, constructs a temporary reference
    file as AECCAR0 + AECCAR2
    3. Runs Bader analysis twice: once for charge, and a second time
    for the charge difference (magnetization density).

    :param path: path to folder to search in
    :param suffix: specific suffix to look for (e.g. '.relax1' for 'CHGCAR.relax1.gz'
    :return: summary dict
    """

    def _get_filepath(filename, warning, path=path, suffix=suffix):
        paths = glob.glob(os.path.join(path, filename + suffix + '*'))
        if not paths:
            warnings.warn(warning)
            return None
        if len(paths) > 1:
            # using reverse=True because, if multiple files are present,
            # they likely have suffixes 'static', 'relax', 'relax2', etc.
            # and this would give 'static' over 'relax2' over 'relax'
            # however, better to use 'suffix' kwarg to avoid this!
            paths.sort(reverse=True)
            warnings.warn('Multiple files detected, using {}'.format(os.path.basename(path)))
        path = paths[0]
        return path

    chgcar_path = _get_filepath('CHGCAR', 'Could not find CHGCAR!')
    chgcar = Chgcar.from_file(chgcar_path)

    aeccar0_path = _get_filepath('AECCAR0', 'Could not find AECCAR0, interpret Bader results with caution.')
    aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

    aeccar2_path = _get_filepath('AECCAR2', 'Could not find AECCAR2, interpret Bader results with caution.')
    aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

    potcar_path = _get_filepath('POTCAR', 'Could not find POTCAR, cannot calculate charge transfer.')
    potcar = Potcar.from_file(potcar_path) if potcar_path else None

    return bader_analysis_from_objects(chgcar, potcar, aeccar0, aeccar2)
Exemple #11
0
 def setUp(self):
     # This is a CHGCAR_sum file with reduced grid size
     chgcar_path = os.path.join(test_dir, "CHGCAR.FePO4")
     chg_FePO4 = Chgcar.from_file(chgcar_path)
     self.chgcar_path = chgcar_path
     self.chg_FePO4 = chg_FePO4
     self.ca_FePO4 = ChargeDensityAnalyzer(chg_FePO4)
     self.s_LiFePO4 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif"))
Exemple #12
0
 def setUp(self):
     # This is a CHGCAR_sum file with reduced grid size
     chgcar_path = os.path.join(test_dir, "CHGCAR.FePO4")
     chg_FePO4 = Chgcar.from_file(chgcar_path)
     self.chgcar_path = chgcar_path
     self.chg_FePO4 = chg_FePO4
     self.ca_FePO4 = ChargeDensityAnalyzer(chg_FePO4)
     self.s_LiFePO4 = Structure.from_file(os.path.join(test_dir, "LiFePO4.cif"))
Exemple #13
0
	def test_density_ncl(self):
		print("TEST DENSITY NCL")
		sys.stdout.flush()
		print("LOAD WAVEFUNCTION")
		sys.stdout.flush()
		wf = NCLWavefunction.from_directory('noncollinear')
		print("FINISHED LOAD WAVEFUNCTION")
		sys.stdout.flush()
		#wf = wf.desymmetrized_copy()
		wf.write_density_realspace(scale = wf.structure.lattice.volume)
		wf.write_density_realspace(dim=np.array([40,40,40]), scale = wf.structure.lattice.volume)
		tstchg = Chgcar.from_file("AECCAR2").data['total']# / wf.structure.volume
		chg = Chgcar.from_file("PYAECCAR").data['total']
		reldiff = np.sqrt(np.mean(((chg-tstchg)/tstchg)**2))
		newchg = chg-tstchg
		Chgcar(Poscar(wf.structure), {'total': newchg}).write_file('DIFFCHGCAR.vasp')
		print(np.sum(chg)/40**3, np.sum(tstchg)/40**3)
		assert_almost_equal(reldiff, 0, decimal=3)
Exemple #14
0
    def test_init(self):
        filepath = os.path.join(test_dir, 'CHGCAR.nospin')
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 2)[0, 1], 0)
        filepath = os.path.join(test_dir, 'CHGCAR.spin')
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1],
                               -0.0043896932237534022)
        #test sum
        chg += chg
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1],
                               -0.0043896932237534022 * 2)

        filepath = os.path.join(test_dir, 'CHGCAR.Fe3O4')
        chg = Chgcar.from_file(filepath)
        ans = [1.56472768, 3.25985108, 3.49205728, 3.66275028, 3.8045896, 5.10813352]
        myans = chg.get_integrated_diff(0, 3, 6)
        self.assertTrue(np.allclose(myans[:, 1], ans))
    def test_init(self):
        filepath = os.path.join(test_dir, 'CHGCAR.nospin')
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 2)[0, 1], 0)
        filepath = os.path.join(test_dir, 'CHGCAR.spin')
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1],
                               -0.0043896932237534022)
        #test sum
        chg += chg
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1],
                               -0.0043896932237534022 * 2)

        filepath = os.path.join(test_dir, 'CHGCAR.Fe3O4')
        chg = Chgcar.from_file(filepath)
        ans = [1.56472768, 3.25985108, 3.49205728, 3.66275028, 3.8045896, 5.10813352]
        myans = chg.get_integrated_diff(0, 3, 6)
        self.assertTrue(np.allclose(myans[:, 1], ans))
Exemple #16
0
	def test_density(self):
		print("TEST DENSITY")
		sys.stdout.flush()
		wf = Wavefunction.from_directory('nosym')
		#wf = wf.desymmetrized_copy()
		wf.write_density_realspace(dim=np.array([40,40,40]), scale = wf.structure.lattice.volume)
		tstchg = Chgcar.from_file("AECCAR2").data['total']# / wf.structure.volume
		chg = Chgcar.from_file("PYAECCAR").data['total']
		reldiff = np.sqrt(np.mean(((chg-tstchg)/tstchg)**2))
		newchg = chg-tstchg
		Chgcar(Poscar(wf.structure), {'total': newchg}).write_file('DIFFCHGCAR.vasp')
		print(np.sum(chg)/40**3, np.sum(tstchg)/40**3)
		assert_almost_equal(reldiff, 0, decimal=2)
		wf = Wavefunction.from_directory('nosym')
		res = wf.write_density_realspace(filename="BAND4DENS", bands=4)
		#os.remove('PYAECCAR')
		print("DENS shape", res.shape)
		assert_almost_equal(np.sum(res)*wf.structure.lattice.volume/np.cumprod(res.shape)[-1], 1, 4)
Exemple #17
0
    def test_init(self):
        filepath = os.path.join(test_dir, 'CHGCAR.nospin')
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 2)[0, 1], 0)
        filepath = os.path.join(test_dir, 'CHGCAR.spin')
        chg = Chgcar.from_file(filepath)
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1],
                               -0.0043896932237534022)
        #test sum
        chg += chg
        self.assertAlmostEqual(chg.get_integrated_diff(0, 1)[0, 1],
                               -0.0043896932237534022 * 2)

        filepath = os.path.join(test_dir, 'CHGCAR.Fe3O4')
        chg = Chgcar.from_file(filepath)
        ans = [1.93313368, 3.91201473, 4.11858277, 4.1240093, 4.10634989,
               3.38864822]
        myans = chg.get_integrated_diff(0, 3, 6)
        self.assertTrue(np.allclose(myans[:, 1], ans))
Exemple #18
0
 def test_write(self):
     filepath = os.path.join(test_dir, 'CHGCAR.spin')
     chg = Chgcar.from_file(filepath)
     chg.write_file("CHGCAR_pmg")
     with open("CHGCAR_pmg") as f:
         for i, line in enumerate(f):
             if i == 22130:
                 self.assertEqual("augmentation occupancies   1  15\n", line)
             if i == 44255:
                 self.assertEqual("augmentation occupancies   1  15\n", line)
     os.remove("CHGCAR_pmg")
 def test_write(self):
     filepath = os.path.join(test_dir, 'CHGCAR.spin')
     chg = Chgcar.from_file(filepath)
     chg.write_file("CHGCAR_pmg")
     with open("CHGCAR_pmg") as f:
         for i, line in enumerate(f):
             if i == 22130:
                 self.assertEqual("augmentation occupancies   1  15\n", line)
             if i == 44255:
                 self.assertEqual("augmentation occupancies   1  15\n", line)
     os.remove("CHGCAR_pmg")
Exemple #20
0
def bader_analysis_from_path(path, suffix=''):
    """
    Convenience method to run Bader analysis on a folder containing
    typical VASP output files.

    This method will:

    1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
    counterparts.
    2. If AECCAR* files are present, constructs a temporary reference
    file as AECCAR0 + AECCAR2
    3. Runs Bader analysis twice: once for charge, and a second time
    for the charge difference (magnetization density).

    :param path: path to folder to search in
    :param suffix: specific suffix to look for (e.g. '.relax1' for 'CHGCAR.relax1.gz'
    :return: summary dict
    """

    chgcar_path = get_filepath('CHGCAR', 'Could not find CHGCAR!', path,
                               suffix)
    chgcar = Chgcar.from_file(chgcar_path)

    aeccar0_path = get_filepath(
        'AECCAR0',
        'Could not find AECCAR0, interpret Bader results with caution.', path,
        suffix)
    aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

    aeccar2_path = get_filepath(
        'AECCAR2',
        'Could not find AECCAR2, interpret Bader results with caution.', path,
        suffix)
    aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

    potcar_path = get_filepath(
        'POTCAR', 'Could not find POTCAR, cannot calculate charge transfer.',
        path, suffix)
    potcar = Potcar.from_file(potcar_path) if potcar_path else None

    return bader_analysis_from_objects(chgcar, potcar, aeccar0, aeccar2)
Exemple #21
0
    def _load_parchg(self):
        if self.preloaded_data:
            with open(os.path.join(self.folder, 'parchg.npy'), 'rb') as p:
                data = np.load(p)
        else:
            parchg = Chgcar.from_file(os.path.join(self.folder, 'PARCHG'))
            data = parchg.data['total']
            np.save(os.path.join(self.folder, 'parchg.npy'), data)

        a_vals = np.linspace(0, 1, data.shape[0])
        b_vals = np.linspace(0, 1, data.shape[1])
        c_vals = np.linspace(0, 1, data.shape[2])

        return data, a_vals, b_vals, c_vals
Exemple #22
0
    def test_soc_chgcar(self):

        filepath = os.path.join(test_dir, "CHGCAR.NiO_SOC.gz")
        chg = Chgcar.from_file(filepath)
        self.assertEqual(set(chg.data.keys()), {'total', 'diff_x', 'diff_y', 'diff_z', 'diff'})
        self.assertTrue(chg.is_soc)
        self.assertEqual(chg.data['diff'].shape, chg.data['diff_y'].shape)

        # check our construction of chg.data['diff'] makes sense
        # this has been checked visually too and seems reasonable
        self.assertEqual(abs(chg.data['diff'][0][0][0]),
                         np.linalg.norm([chg.data['diff_x'][0][0][0],
                                         chg.data['diff_y'][0][0][0],
                                         chg.data['diff_z'][0][0][0]]))

        # and that the net magnetization is about zero
        # note: we get ~ 0.08 here, seems a little high compared to
        # vasp output, but might be due to chgcar limitations?
        self.assertAlmostEqual(chg.net_magnetization, 0.0, places=0)

        chg.write_file("CHGCAR_pmg_soc")
        chg_from_file = Chgcar.from_file("CHGCAR_pmg_soc")
        self.assertTrue(chg_from_file.is_soc)
        os.remove("CHGCAR_pmg_soc")
Exemple #23
0
    def __init__(self, chgcar_filename, potcar_filename=None):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename: The filename of the CHGCAR.
            potcar_filename: Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
        """
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)

        with ScratchDir(".") as temp_dir:
            shutil.copy(chgcarpath, os.path.join(temp_dir, "CHGCAR"))

            rs = subprocess.Popen(["bader", "CHGCAR"],
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE, close_fds=True)
            rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError("bader exited with return code %d. "
                                   "Pls check your bader installation."
                                   % rs.returncode)
            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = [s.lower() for s in raw.pop(0).split()]
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers[1:], vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data
Exemple #24
0
    def from_chgcar_poscar(cls, chgcar, poscar):
        """
        Build a :class`Density` object from Vasp data.

        Args:
            chgcar: Either string with the name of a CHGCAR file or :class:`Chgcar` pymatgen object.
            poscar: Either string with the name of a POSCAR file or :class:`Poscar` pymatgen object.

        .. warning:

            The present version does not support non-collinear calculations.
            The Chgcar object provided by pymatgen does not provided enough information
            to understand if the calculation is collinear or no.
        """
        if is_string(chgcar):
            chgcar = Chgcar.from_file(chgcar)
        if is_string(poscar):
            poscar = Poscar.from_file(poscar, check_for_POTCAR=False, read_velocities=False)

        nx, ny, nz = chgcar.dim
        nspinor = 1
        nsppol = 2 if chgcar.is_spin_polarized else 1
        nspden = 2 if nsppol == 2 else 1

        # Convert pymatgen chgcar data --> abipy representation.
        abipy_datar = np.empty((nspden, nx, ny, nz))

        if nspinor == 1:
            if nsppol == 1:
                abipy_datar = chgcar.data["total"]
            elif nsppol == 2:
                total, diff = chgcar.data["total"], chgcar.data["diff"]
                abipy_datar[0] = 0.5 * (total + diff)
                abipy_datar[1] = 0.5 * (total - diff)
            else:
                raise ValueError("Wrong nspden %s" % nspden)

        else:
            raise NotImplementedError("nspinor == 2 requires more info in Chgcar")

        # density in Chgcar is multiplied by volume!
        abipy_datar /= poscar.structure.volume

        return cls(nspinor=nspinor, nsppol=nsppol, nspden=nspden, datar=abipy_datar,
                   structure=poscar.structure, iorder="c")
Exemple #25
0
        def callback_update_structure(contents, filename, last_modified):

            if not contents:
                raise PreventUpdate

            # assume we only want the first input for now
            content_type, content_string = contents.split(",")
            decoded_contents = b64decode(content_string)

            error = None
            data = None

            # necessary to write to file so pymatgen's filetype detection can work
            with NamedTemporaryFile(suffix=filename) as tmp:
                tmp.write(decoded_contents)
                tmp.flush()
                try:
                    struct_or_mol = Structure.from_file(tmp.name)
                    data = self.to_data(struct_or_mol)
                except:
                    try:
                        struct_or_mol = Molecule.from_file(tmp.name)
                        data = self.to_data(struct_or_mol)
                    except:
                        try:
                            struct_or_mol = Chgcar.from_file(tmp.name)
                        except:
                            # TODO: fix these horrible try/excepts, loadfn may be dangerous
                            try:
                                struct_or_mol = loadfn(tmp.name)
                                data = self.to_data(struct_or_mol)
                            except:
                                error = (
                                    "Could not parse uploaded file. "
                                    "If this seems like a bug, please report it. "
                                    "Crystal Toolkit understands all crystal "
                                    "structure file types and molecule file types "
                                    "supported by pymatgen.")

            return {
                "data": data,
                "error": error,
                "time_requested": self.get_time()
            }
Exemple #26
0
    def __init__(self, chgcar_filename, potcar_filename=None):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename: The filename of the CHGCAR.
            potcar_filename: Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
        """
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)

        with ScratchDir(".") as temp_dir:
            shutil.copy(chgcarpath, os.path.join(temp_dir, "CHGCAR"))

            rs = subprocess.Popen(["bader", "CHGCAR"],
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE,
                                  close_fds=True)
            rs.communicate()
            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = [s.lower() for s in raw.pop(0).split()]
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers[1:], vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data
Exemple #27
0
    def __init__(self, filename):
        """
        Reads PARCHG file and make class attributes
        """
        self.filename = filename
        self.parchg = Chgcar.from_file(filename)

        # charge data from CHGCAR
        self.chgdata = self.parchg.data['total']

        # structure associated w/ volumetric data
        self.structure = self.parchg.structure

        # fraction of cell occupied by structure
        self.zmax = self.structure.cart_coords[:, 2].max() \
                            / self.structure.lattice.c
        # max charge density
        # rmax should be maximum rho value within the stm_cell
        # i.e., [X, Y, Z[nzmin:nzmax]] rather than the whole box
        self.rmax = None
Exemple #28
0
def get_chg_matrix(folder):
    chg = Chgcar.from_file(os.path.join(folder, 'CHGCAR'))
    chg_matrix = chg.data['total'] / chg.ngridpts
    potcar = Potcar.from_file(os.path.join(folder, 'POTCAR'))
    poscar = Poscar.from_file(os.path.join(folder, 'POSCAR'))
    natoms = poscar.natoms
    cumm_natoms = np.array([sum(natoms[0:i + 1]) for i in range(len(natoms))])

    lengths = []
    for i in range(3):
        lengths.append(len(chg.get_axis_grid(i)))
    lengths = np.array(lengths)

    for atom in range(len(chg.structure.sites)):  # iterating over ion centers
        potcarsingle = potcar[np.argmax(cumm_natoms >= (atom+1))]  # get Potcarsingle for each atom
        charge = potcarsingle.nelectrons
        site = chg.structure.sites[atom]  # atoms are 1 indexed
        # number = site.species_and_occu.elements[0].number
        i = np.round(np.array([site.a, site.b, site.c]) * lengths)  # getting indecies to place atomic charges in cell
        chg_matrix[int(i[0] % lengths[0])][int(i[1] % lengths[1])][int(i[2] % lengths[2])] -= (charge)  # placing ionic centers in cell

    return -chg_matrix
Exemple #29
0
    def test_hdf5(self):
        chgcar = Chgcar.from_file(os.path.join(test_dir, "CHGCAR.NiO_SOC.gz"))
        chgcar.to_hdf5("chgcar_test.hdf5")
        import h5py
        with h5py.File("chgcar_test.hdf5", "r") as f:
            self.assertArrayAlmostEqual(np.array(f["vdata"]["total"]),
                                        chgcar.data["total"])
            self.assertArrayAlmostEqual(np.array(f["vdata"]["diff"]),
                                        chgcar.data["diff"])
            self.assertArrayAlmostEqual(np.array(f["lattice"]),
                                        chgcar.structure.lattice.matrix)
            self.assertArrayAlmostEqual(np.array(f["fcoords"]),
                                        chgcar.structure.frac_coords)
            for z in f["Z"]:
                self.assertIn(z, [Element.Ni.Z, Element.O.Z])

            for sp in f["species"]:
                self.assertIn(sp, ["Ni", "O"])

        chgcar2 = Chgcar.from_hdf5("chgcar_test.hdf5")
        self.assertArrayAlmostEqual(chgcar2.data["total"],
                                    chgcar.data["total"])

        os.remove("chgcar_test.hdf5")
Exemple #30
0
    def from_path(cls, path, suffix="", zpsp=None):
        """
        Convenience method to run critic2 analysis on a folder containing
        typical VASP output files.
        This method will:

        1. Look for files CHGCAR, AECAR0, AECAR2, POTCAR or their gzipped
        counterparts.

        2. If AECCAR* files are present, constructs a temporary reference
        file as AECCAR0 + AECCAR2.

        3. Runs critic2 analysis twice: once for charge, and a second time
        for the charge difference (magnetization density).

        :param path: path to folder to search in
        :param suffix: specific suffix to look for (e.g. '.relax1' for
            'CHGCAR.relax1.gz')
        :param zpsp: manually specify ZPSP if POTCAR not present
        :return:
        """
        def _get_filepath(filename, warning, path=path, suffix=suffix):
            paths = glob.glob(os.path.join(path, filename + suffix + "*"))
            if not paths:
                warnings.warn(warning)
                return None
            if len(paths) > 1:
                # using reverse=True because, if multiple files are present,
                # they likely have suffixes 'static', 'relax', 'relax2', etc.
                # and this would give 'static' over 'relax2' over 'relax'
                # however, better to use 'suffix' kwarg to avoid this!
                paths.sort(reverse=True)
                warnings.warn("Multiple files detected, using {}".format(
                    os.path.basename(path)))
            path = paths[0]
            return path

        chgcar_path = _get_filepath("CHGCAR", "Could not find CHGCAR!")
        chgcar = Chgcar.from_file(chgcar_path)
        chgcar_ref = None

        if not zpsp:

            potcar_path = _get_filepath(
                "POTCAR",
                "Could not find POTCAR, will not be able to calculate charge transfer.",
            )

            if potcar_path:
                potcar = Potcar.from_file(potcar_path)
                zpsp = {p.symbol: p.zval for p in potcar}

        if not zpsp:

            # try and get reference "all-electron-like" charge density if zpsp not present
            aeccar0_path = _get_filepath(
                "AECCAR0",
                "Could not find AECCAR0, interpret Bader results with caution.",
            )
            aeccar0 = Chgcar.from_file(aeccar0_path) if aeccar0_path else None

            aeccar2_path = _get_filepath(
                "AECCAR2",
                "Could not find AECCAR2, interpret Bader results with caution.",
            )
            aeccar2 = Chgcar.from_file(aeccar2_path) if aeccar2_path else None

            chgcar_ref = aeccar0.linear_add(aeccar2) if (aeccar0
                                                         and aeccar2) else None

        return cls(chgcar.structure, chgcar, chgcar_ref, zpsp=zpsp)
Exemple #31
0
 def from_file(cls, chgcar_filename):
     chgcar = Chgcar.from_file(chgcar_filename)
     return cls(chgcar=chgcar)
Exemple #32
0
def asym(chg, n):
    data = []
    for j in range(chg.dim[1]):
        for i in range(chg.dim[0]):
            for k in range(chg.dim[2]):
                if i + k == int(chg.dim[0] + chg.dim[2]) / 2 + n:
                    data.append(chg.data['total'][i, j, k])

    data = np.array(data)
    data = np.reshape(data, (chg.dim[1], len(data) // chg.dim[1]))
    return data.astype(float)


os.chdir('/home/jinho93/molecule/ddt/vasp/2020/bulk/sym/t1')
chgcar = Chgcar.from_file('SPIN.vasp')
dsym = sym(chgcar, 5)

os.chdir('/home/jinho93/molecule/ddt/vasp/2020/bulk/asym/t1')
chgcar = Chgcar.from_file('SPIN.vasp')
dasym = asym(chgcar, 5)

#%%
os.chdir('/home/jinho93/molecule/ddt/vasp/2020/bulk/sym/t1')
chgcar = Chgcar.from_file('SPIN.vasp')
mlist = []
for i in range(25):
    mlist.append(np.max(sym(chgcar, i)))
print(np.argmax(mlist), mlist[np.argmax(mlist)])

# %%
Exemple #33
0
    def __init__(self,
                 chgcar_filename,
                 potcar_filename=None,
                 chgref_filename=None,
                 parse_atomic_densities=False):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename (str): The filename of the CHGCAR.
            potcar_filename (str): Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
            chgref_filename (str): Optional. The filename of the reference
                CHGCAR, which calculated by AECCAR0 + AECCAR2. (See
                http://theory.cm.utexas.edu/henkelman/code/bader/ for details.)
            parse_atomic_densities (bool): Optional. turns on atomic partition of the charge density
                charge densities are atom centered

        """
        if not BADEREXE:
            raise RuntimeError(
                "BaderAnalysis requires the executable bader to be in the path."
                " Please download the library at http://theory.cm.utexas"
                ".edu/vasp/bader/ and compile the executable.")
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)
        chgrefpath = os.path.abspath(
            chgref_filename) if chgref_filename else None
        self.reference_used = bool(chgref_filename)
        self.parse_atomic_densities = parse_atomic_densities
        with ScratchDir("."):
            with zopen(chgcarpath, 'rt') as f_in:
                with open("CHGCAR", "wt") as f_out:
                    shutil.copyfileobj(f_in, f_out)
            args = [BADEREXE, "CHGCAR"]
            if chgref_filename:
                with zopen(chgrefpath, 'rt') as f_in:
                    with open("CHGCAR_ref", "wt") as f_out:
                        shutil.copyfileobj(f_in, f_out)
                args += ['-ref', 'CHGCAR_ref']
            if parse_atomic_densities:
                args += ['-p', 'all_atom']
            rs = subprocess.Popen(args,
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE,
                                  close_fds=True)
            stdout, stderr = rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError("bader exited with return code %d. "
                                   "Please check your bader installation." %
                                   rs.returncode)

            try:
                self.version = float(stdout.split()[5])
            except Exception:
                self.version = -1  # Unknown
            if self.version < 1.0:
                warnings.warn('Your installed version of Bader is outdated, '
                              'calculation of vacuum charge may be incorrect.')

            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = ('x', 'y', 'z', 'charge', 'min_dist', 'atomic_vol')
                raw.pop(0)
                raw.pop(0)
                while True:
                    line = raw.pop(0).strip()
                    if line.startswith("-"):
                        break
                    vals = map(float, line.split()[1:])
                    data.append(dict(zip(headers, vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data

            if self.parse_atomic_densities:
                # convert the charge denisty for each atom spit out by Bader into Chgcar objects for easy parsing
                atom_chgcars = [
                    Chgcar.from_file("BvAt{}.dat".format(str(i).zfill(4)))
                    for i in range(1,
                                   len(self.chgcar.structure) + 1)
                ]

                atomic_densities = []
                # For each atom in the structure
                for atom, loc, chg in zip(self.chgcar.structure,
                                          self.chgcar.structure.frac_coords,
                                          atom_chgcars):
                    # Find the index of the atom in the charge density atom
                    index = np.round(np.multiply(loc, chg.dim))

                    data = chg.data['total']
                    # Find the shift vector in the array
                    shift = (np.divide(chg.dim, 2) - index).astype(int)

                    # Shift the data so that the atomic charge density to the center for easier manipulation
                    shifted_data = np.roll(data, shift, axis=(0, 1, 2))

                    # Slices a central window from the data array
                    def slice_from_center(data, xwidth, ywidth, zwidth):
                        x, y, z = data.shape
                        startx = x // 2 - (xwidth // 2)
                        starty = y // 2 - (ywidth // 2)
                        startz = z // 2 - (zwidth // 2)
                        return data[startx:startx + xwidth,
                                    starty:starty + ywidth,
                                    startz:startz + zwidth]

                    # Finds the central encompassing volume which holds all the data within a precision
                    def find_encompassing_vol(data, prec=1e-3):
                        total = np.sum(data)
                        for i in range(np.max(data.shape)):
                            sliced_data = slice_from_center(data, i, i, i)
                            if total - np.sum(sliced_data) < 0.1:
                                return sliced_data
                        return None

                    d = {
                        "data": find_encompassing_vol(shifted_data),
                        "shift": shift,
                        "dim": self.chgcar.dim
                    }
                    atomic_densities.append(d)
                self.atomic_densities = atomic_densities
Exemple #34
0
VASP chgcar file is required
'''

import sys
import json
import numpy as np
from pymatgen.io.vasp.outputs import Chgcar
from ase.calculators.vasp import VaspChargeDensity
from PIL import Image

from ChargeDensity.image_file_process import charge_file_crop_2d
from CrystalToolkit.geometry_properties import symmetry_order_2d, rectangle_transform_2d
from CrystalToolkit.vasp_chgcar import chgcar_file_slice_2d, charge_file_2d_reformat

file_chgcar = sys.argv[1]
stru = Chgcar.from_file(file_chgcar).poscar.structure
'''
# find the symmetry order of the 2D structure
with open('data.json') as json_file:
    symmetry_data = json.load(json_file)
point_group_list = symmetry_data['point_group_list']
symmetry_order_2d(structure=stru, point_group_list=point_group_list)
'''
# slice the vasp chgcar file into 2D
vasp_charge = VaspChargeDensity(filename=file_chgcar)
density = vasp_charge.chg[-1]
atoms = vasp_charge.atoms[-1]
*_, chgden_2d = chgcar_file_slice_2d(density=density, atoms=atoms)
# change to RGB values, type must be unit 8 otherwise PIL will complain
chgden_2d = (255.0 / chgden_2d.max() * (chgden_2d - chgden_2d.min())).astype(
    np.uint8)
Exemple #35
0
def neb(directory,
        nimages=7,
        functional=("pbe", {}),
        is_metal=False,
        is_migration=False):
    """
    Set up the NEB calculation from the initial and final structures.

    Args:
        directory (str): Directory in which the transition calculations should be
            set up.
        functional (tuple): Tuple with the functional choices. The first element
            contains a string that indicates the functional used ("pbe", "hse", ...),
            whereas the second element contains a dictionary that allows the user
            to specify the various functional tags.
        nimages (int): Number of images to use in the NEB calculation.
        is_metal (bool): Flag that indicates the material being studied is a
            metal, which changes the smearing from Gaussian to second order
            Methfessel-Paxton of 0.2 eV.
        is_migration (bool): Flag that indicates that the transition is a migration
            of an atom in the structure.

    Returns:
        None

    """
    directory = os.path.abspath(directory)

    # Extract the optimized initial and final geometries
    initial_dir = os.path.join(directory, "initial")
    final_dir = os.path.join(directory, "final")

    try:
        # Check to see if the initial final_cathode structure is present
        initial_structure = Cathode.from_file(
            os.path.join(initial_dir,
                         "final_cathode.json")).as_ordered_structure()

    except FileNotFoundError:
        # In case the required json file is not present, check to see if
        # there is VASP output which can be used
        initial_structure = Structure.from_file(
            os.path.join(initial_dir, "CONTCAR"))

        # Add the magnetic configuration to the initial structure
        initial_out = Outcar(os.path.join(initial_dir, "OUTCAR"))
        initial_magmom = [site["tot"] for site in initial_out.magnetization]

        try:
            initial_structure.add_site_property("magmom", initial_magmom)
        except ValueError:
            if len(initial_magmom) == 0:
                print("No magnetic moments found in OUTCAR file. Setting "
                      "magnetic moments to zero.")
                initial_magmom = [0] * len(initial_structure)
                initial_structure.add_site_property("magmom", initial_magmom)
            else:
                raise ValueError("Number of magnetic moments in OUTCAR file "
                                 "do not match the number of sites!")
    except BaseException:
        raise FileNotFoundError("Could not find required structure "
                                "information in " + initial_dir + ".")

    try:
        final_structure = Structure.from_file(
            os.path.join(final_dir, "CONTCAR"))
    except FileNotFoundError:
        final_structure = Cathode.from_file(
            os.path.join(final_dir,
                         "final_cathode.json")).as_ordered_structure()

    # In case the transition is a migration
    if is_migration:
        # Set up the static potential for the Pathfinder from the host charge
        # density
        host_charge_density = Chgcar.from_file(os.path.join(directory, "host"))
        host_potential = ChgcarPotential(host_charge_density)

        migration_site_index = find_migrating_ion(initial_structure,
                                                  final_structure)

        neb_path = NEBPathfinder(start_struct=initial_structure,
                                 end_struct=final_structure,
                                 relax_sites=migration_site_index,
                                 v=host_potential)

        images = neb_path.images
        neb_path.plot_images("neb.vasp")

    # In case an "middle image" has been provided via which to interpolate
    elif os.path.exists(os.path.join(directory, "middle")):
        print("Found a 'middle' directory in the NEB directory. Interpolating "
              "via middle geometry.")
        # Load the middle image
        middle_structure = Structure.from_file(
            os.path.join(directory, "middle", "CONTCAR"))
        # Perform an interpolation via this image
        images_1 = initial_structure.interpolate(
            end_structure=middle_structure,
            nimages=int((nimages + 1) / 2),
            interpolate_lattices=True)
        images_2 = middle_structure.interpolate(end_structure=final_structure,
                                                nimages=int((nimages) / 2 + 1),
                                                interpolate_lattices=True)

        images = images_1[:-1] + images_2

    else:
        # Linearly interpolate the initial and final structures
        images = initial_structure.interpolate(end_structure=final_structure,
                                               nimages=nimages + 1,
                                               interpolate_lattices=True)

    # TODO Add functionality for NEB calculations with changing lattices

    user_incar_settings = {}

    # Set up the functional
    if functional[0] != "pbe":
        functional_config = _load_yaml_config(functional[0] + "Set")
        functional_config["INCAR"].update(functional[1])
        user_incar_settings.update(functional_config["INCAR"])

    # Add the standard Methfessel-Paxton smearing for metals
    if is_metal:
        user_incar_settings.update({"ISMEAR": 2, "SIGMA": 0.2})

    neb_calculation = PybatNEBSet(images,
                                  potcar_functional=DFT_FUNCTIONAL,
                                  user_incar_settings=user_incar_settings)

    # Set up the NEB calculation
    neb_calculation.write_input(directory)

    # Make a file to visualize the transition
    neb_calculation.visualize_transition(
        os.path.join(directory, "transition.cif"))
Exemple #36
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
Exemple #37
0
def dipole_chgcar(args):
    # Getting info about the cell
    print('Getting Electron Densities...', end='')
    sys.stdout.flush()
    chg = Chgcar.from_file('BvAt_summed.dat')
    s = chg.structure
    d = chg.data['total'] / chg.ngridpts   # get charge density in e-/A^2
    lengths = []
    for i in range(3):
        lengths.append(len(chg.get_axis_grid(i)))
    lengths = np.array(lengths)
    print('done')

    # Adding ionic centers to cell
    print('Adding Ions to Cell...', end='')
    sys.stdout.flush()
    poscar = Poscar.from_file('POSCAR')
    potcar = Potcar.from_file('POTCAR')
    natoms = poscar.natoms
    cumm_natoms = np.array([ sum(natoms[0:i+1]) for i in range(len(natoms)) ])
    for atom in args.atoms:   # iterating over ion centers
        potcarsingle = potcar[np.argmax(cumm_natoms>=atom)] # get Potcarsingle for each atom
        charge = potcarsingle.nelectrons
        site = s.sites[atom - 1] # atoms are 1 indexed
        # number = site.species_and_occu.elements[0].number
        i = np.round(np.array([site.a, site.b, site.c]) * lengths)  # getting indecies to place atomic charges in cell
        d[i[0] % lengths[0]][i[1] % lengths[1]][i[2] % lengths[2]] -= (charge)  # placing ionic centers in cell
    print('done')

    # Make correction for charged species
    print('Calculating Correction for Charged Species...', end='')
    sys.stdout.flush()
    element_charge = sum(sum(sum(d)))
    bader_gridpts = len(np.nonzero(d)[2])# number of gridpoints in bader volume
    correction = element_charge / bader_gridpts  # normalization constant to account for charged species
    print('done')
    print('\nCharge = ' + str(-element_charge) + ' e-\n')
    # print('\nCorrection = ' + str(correction) + ' e-\n')

    # Calculating lattice
    #axis = np.array(args.axis) # / np.linalg.norm(np.array(args.axis))
    cart_axis = np.matrix(args.axis) * s.lattice.matrix
    unit_vector = cart_axis / np.linalg.norm((cart_axis))
    a_axis = chg.get_axis_grid(0)
    b_axis = chg.get_axis_grid(1)
    c_axis = chg.get_axis_grid(2)
    len_a = len(a_axis)
    len_b = len(b_axis)
    len_c = len(c_axis)
    mod_a = int(np.round(float(len_a) * args.origin[0]))
    mod_b = int(np.round(float(len_b) * args.origin[1]))
    mod_c = int(np.round(float(len_c) * args.origin[2]))
    mat = s.lattice.matrix
    def get_first_moment(a, b, c, x):
        a = float((a - mod_a) % len_a) / len_a
        b = float((b - mod_b) % len_b) / len_b
        c = float((c - mod_c) % len_c) / len_c
        cart_vector = np.matrix([a, b, c]) * mat
        return float(np.dot(cart_vector, unit_vector.transpose())) * (x - correction)

    # integrate over charge density
    print('Calculating Dipole... ')
    sys.stdout.flush()
    dipole = 0
    for a in range(lengths[0]):
        sys.stdout.write('\r%d percent' % int(a * 100 / len_a))
        sys.stdout.flush()
        for b in range(lengths[1]):
            for c in range(lengths[2]):
                x = d[a][b][c]
                if x != 0:
                    dipole += get_first_moment(a, b, c, x)
    print('done')
    print('Dipole = ' + str(dipole) + ' eA')
    print('Dipole = ' + str(dipole / 0.20819434) + ' D')
    return dipole
    sys.stdout.flush()
Exemple #38
0
    def __init__(
        self,
        chgcar_filename=None,
        potcar_filename=None,
        chgref_filename=None,
        parse_atomic_densities=False,
        cube_filename=None,
    ):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename (str): The filename of the CHGCAR.
            potcar_filename (str): The filename of the POTCAR.
            chgref_filename (str): The filename of the reference charge density.
            parse_atomic_densities (bool): Optional. turns on atomic partition of the charge density
                charge densities are atom centered
            cube_filename (str): Optional. The filename of the cube file.
        """
        if not BADEREXE:
            raise RuntimeError(
                "BaderAnalysis requires the executable bader to be in the path."
                " Please download the library at http://theory.cm.utexas"
                ".edu/vasp/bader/ and compile the executable.")

        if not (cube_filename or chgcar_filename):
            raise ValueError("You must provide either a cube file or a CHGCAR")
        if cube_filename and chgcar_filename:
            raise ValueError(
                "You cannot parse a cube and a CHGCAR at the same time.")
        self.parse_atomic_densities = parse_atomic_densities

        if chgcar_filename:
            fpath = os.path.abspath(chgcar_filename)
            self.is_vasp = True
            self.chgcar = Chgcar.from_file(fpath)
            self.structure = self.chgcar.structure
            self.potcar = Potcar.from_file(
                potcar_filename) if potcar_filename is not None else None
            self.natoms = self.chgcar.poscar.natoms
            chgrefpath = os.path.abspath(
                chgref_filename) if chgref_filename else None
            self.reference_used = bool(chgref_filename)

            # List of nelects for each atom from potcar
            potcar_indices = []
            for i, v in enumerate(self.natoms):
                potcar_indices += [i] * v
            self.nelects = ([
                self.potcar[potcar_indices[i]].nelectrons
                for i in range(len(self.structure))
            ] if self.potcar else [])

        else:
            fpath = os.path.abspath(cube_filename)
            self.is_vasp = False
            self.cube = Cube(fpath)
            self.structure = self.cube.structure
            self.nelects = None
            chgrefpath = os.path.abspath(
                chgref_filename) if chgref_filename else None
            self.reference_used = bool(chgref_filename)

        with ScratchDir("."):
            tmpfile = "CHGCAR" if chgcar_filename else "CUBE"
            with zopen(fpath, "rt") as f_in:
                with open(tmpfile, "wt") as f_out:
                    shutil.copyfileobj(f_in, f_out)
            args = [BADEREXE, tmpfile]
            if chgref_filename:
                with zopen(chgrefpath, "rt") as f_in:
                    with open("CHGCAR_ref", "wt") as f_out:
                        shutil.copyfileobj(f_in, f_out)
                args += ["-ref", "CHGCAR_ref"]
            if parse_atomic_densities:
                args += ["-p", "all_atom"]
            with subprocess.Popen(args,
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE,
                                  close_fds=True) as rs:
                stdout, _ = rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError(
                    f"bader exited with return code {rs.returncode}. Please check your bader installation."
                )

            try:
                self.version = float(stdout.split()[5])
            except ValueError:
                self.version = -1  # Unknown
            if self.version < 1.0:
                warnings.warn(
                    "Your installed version of Bader is outdated, calculation of vacuum charge may be incorrect.",
                    UserWarning,
                )

            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = ("x", "y", "z", "charge", "min_dist", "atomic_vol")
                raw.pop(0)
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers, vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data

            if self.parse_atomic_densities:
                # convert the charge density for each atom spit out by Bader into Chgcar objects for easy parsing
                atom_chgcars = [
                    Chgcar.from_file(f"BvAt{str(i).zfill(4)}.dat")
                    for i in range(1,
                                   len(self.chgcar.structure) + 1)
                ]

                atomic_densities = []
                # For each atom in the structure
                for _, loc, chg in zip(
                        self.chgcar.structure,
                        self.chgcar.structure.frac_coords,
                        atom_chgcars,
                ):
                    # Find the index of the atom in the charge density atom
                    index = np.round(np.multiply(loc, chg.dim))

                    data = chg.data["total"]
                    # Find the shift vector in the array
                    shift = (np.divide(chg.dim, 2) - index).astype(int)

                    # Shift the data so that the atomic charge density to the center for easier manipulation
                    shifted_data = np.roll(data, shift, axis=(0, 1, 2))

                    # Slices a central window from the data array
                    def slice_from_center(data, xwidth, ywidth, zwidth):
                        x, y, z = data.shape
                        startx = x // 2 - (xwidth // 2)
                        starty = y // 2 - (ywidth // 2)
                        startz = z // 2 - (zwidth // 2)
                        return data[startx:startx + xwidth,
                                    starty:starty + ywidth,
                                    startz:startz + zwidth, ]

                    # Finds the central encompassing volume which holds all the data within a precision
                    def find_encompassing_vol(data):
                        total = np.sum(data)
                        for i in range(np.max(data.shape)):
                            sliced_data = slice_from_center(data, i, i, i)
                            if total - np.sum(sliced_data) < 0.1:
                                return sliced_data
                        return None

                    d = {
                        "data": find_encompassing_vol(shifted_data),
                        "shift": shift,
                        "dim": self.chgcar.dim,
                    }
                    atomic_densities.append(d)
                self.atomic_densities = atomic_densities
    def __init__(
        self,
        path=None,
        atomic_densities_path=None,
        run_chargemol=True,
    ):
        """
        Initializes the Chargemol Analysis.

        Args:
            path (str): Path to the CHGCAR, POTCAR, AECCAR0, and AECCAR files.
            Note that it doesn't matter if the files gzip'd or not.
                Default: None (current working directory).
            atomic_densities_path (str|None): Path to the atomic densities directory
            required by Chargemol. If None, Pymatgen assumes that this is
            defined in a "DDEC6_ATOMIC_DENSITIES_DIR" environment variable.
            Only used if run_chargemol is True.
                Default: None.
            run_chargemol (bool): Whether to run the Chargemol analysis. If False,
            the existing Chargemol output files will be read from path.
                Default: True.
        """
        if not path:
            path = os.getcwd()
        if run_chargemol and not (which("Chargemol_09_26_2017_linux_parallel")
                                  or which("Chargemol_09_26_2017_linux_serial")
                                  or which("chargemol"), ):
            raise OSError(
                "ChargemolAnalysis requires the Chargemol executable to be in the path."
                " Please download the library at https://sourceforge.net/projects/ddec/files"
                "and follow the instructions.")
        if atomic_densities_path == "":
            atomic_densities_path = os.getcwd()
        self._atomic_densities_path = atomic_densities_path

        self._chgcarpath = self._get_filepath(path, "CHGCAR")
        self._potcarpath = self._get_filepath(path, "POTCAR")
        self._aeccar0path = self._get_filepath(path, "AECCAR0")
        self._aeccar2path = self._get_filepath(path, "AECCAR2")
        if run_chargemol and not (self._chgcarpath and self._potcarpath
                                  and self._aeccar0path and self._aeccar2path):
            raise FileNotFoundError(
                "CHGCAR, AECCAR0, AECCAR2, and POTCAR are all needed for Chargemol."
            )
        if self._chgcarpath:
            self.chgcar = Chgcar.from_file(self._chgcarpath)
            self.structure = self.chgcar.structure
            self.natoms = self.chgcar.poscar.natoms
        else:
            self.chgcar = None
            self.structure = None
            self.natoms = None
            warnings.warn(
                "No CHGCAR found. Some properties may be unavailable.",
                UserWarning)
        if self._potcarpath:
            self.potcar = Potcar.from_file(self._potcarpath)
        else:
            warnings.warn(
                "No POTCAR found. Some properties may be unavailable.",
                UserWarning)
        self.aeccar0 = Chgcar.from_file(
            self._aeccar0path) if self._aeccar0path else None
        self.aeccar2 = Chgcar.from_file(
            self._aeccar2path) if self._aeccar2path else None

        if run_chargemol:
            self._execute_chargemol()
        else:
            self._from_data_dir(chargemol_output_path=path)
Exemple #40
0
    def __init__(self, chgcar_filename, potcar_filename=None,
                 chgref_filename=None, parse_atomic_densities=False):
        """
        Initializes the Bader caller.

        Args:
            chgcar_filename (str): The filename of the CHGCAR.
            potcar_filename (str): Optional: the filename of the corresponding
                POTCAR file. Used for calculating the charge transfer. If
                None, the get_charge_transfer method will raise a ValueError.
            chgref_filename (str): Optional. The filename of the reference
                CHGCAR, which calculated by AECCAR0 + AECCAR2. (See
                http://theory.cm.utexas.edu/henkelman/code/bader/ for details.)
            parse_atomic_densities (bool): Optional. turns on atomic partition of the charge density
                charge densities are atom centered

        """
        if not BADEREXE:
            raise RuntimeError(
                "BaderAnalysis requires the executable bader to be in the path."
                " Please download the library at http://theory.cm.utexas"
                ".edu/vasp/bader/ and compile the executable.")
        self.chgcar = Chgcar.from_file(chgcar_filename)
        self.potcar = Potcar.from_file(potcar_filename) \
            if potcar_filename is not None else None
        self.natoms = self.chgcar.poscar.natoms
        chgcarpath = os.path.abspath(chgcar_filename)
        chgrefpath = os.path.abspath(chgref_filename) if chgref_filename else None
        self.reference_used = True if chgref_filename else False
        self.parse_atomic_densities = parse_atomic_densities
        with ScratchDir(".") as temp_dir:
            with zopen(chgcarpath, 'rt') as f_in:
                with open("CHGCAR", "wt") as f_out:
                    shutil.copyfileobj(f_in, f_out)
            args = [BADEREXE, "CHGCAR"]
            if chgref_filename:
                with zopen(chgrefpath, 'rt') as f_in:
                    with open("CHGCAR_ref", "wt") as f_out:
                        shutil.copyfileobj(f_in, f_out)
                args += ['-ref', 'CHGCAR_ref']
            if parse_atomic_densities:
                args += ['-p', 'all_atom']
            rs = subprocess.Popen(args,
                                  stdout=subprocess.PIPE,
                                  stdin=subprocess.PIPE, close_fds=True)
            stdout, stderr = rs.communicate()
            if rs.returncode != 0:
                raise RuntimeError("bader exited with return code %d. "
                                   "Please check your bader installation."
                                   % rs.returncode)

            try:
                self.version = float(stdout.split()[5])
            except:
                self.version = -1  # Unknown
            if self.version < 1.0:
                warnings.warn('Your installed version of Bader is outdated, '
                              'calculation of vacuum charge may be incorrect.')

            data = []
            with open("ACF.dat") as f:
                raw = f.readlines()
                headers = ('x', 'y', 'z', 'charge', 'min_dist', 'atomic_vol')
                raw.pop(0)
                raw.pop(0)
                while True:
                    l = raw.pop(0).strip()
                    if l.startswith("-"):
                        break
                    vals = map(float, l.split()[1:])
                    data.append(dict(zip(headers, vals)))
                for l in raw:
                    toks = l.strip().split(":")
                    if toks[0] == "VACUUM CHARGE":
                        self.vacuum_charge = float(toks[1])
                    elif toks[0] == "VACUUM VOLUME":
                        self.vacuum_volume = float(toks[1])
                    elif toks[0] == "NUMBER OF ELECTRONS":
                        self.nelectrons = float(toks[1])
            self.data = data

            if self.parse_atomic_densities:
                # convert the charge denisty for each atom spit out by Bader into Chgcar objects for easy parsing
                atom_chgcars = [Chgcar.from_file("BvAt{}.dat".format(str(i).zfill(4))) for i in
                                range(1, len(self.chgcar.structure) + 1)]

                atomic_densities = []
                # For each atom in the structure
                for atom, loc, chg in zip(self.chgcar.structure,
                                          self.chgcar.structure.frac_coords,
                                          atom_chgcars):
                    # Find the index of the atom in the charge density atom
                    index = np.round(np.multiply(loc, chg.dim))

                    data = chg.data['total']
                    # Find the shift vector in the array
                    shift = (np.divide(chg.dim, 2) - index).astype(int)

                    # Shift the data so that the atomic charge density to the center for easier manipulation
                    shifted_data = np.roll(data, shift, axis=(0, 1, 2))

                    # Slices a central window from the data array
                    def slice_from_center(data, xwidth, ywidth, zwidth):
                        x, y, z = data.shape
                        startx = x // 2 - (xwidth // 2)
                        starty = y // 2 - (ywidth // 2)
                        startz = z // 2 - (zwidth // 2)
                        return data[startx:startx + xwidth, starty:starty + ywidth, startz:startz + zwidth]

                    # Finds the central encompassing volume which holds all the data within a precision
                    def find_encompassing_vol(data,prec=1e-3):
                        total = np.sum(data)
                        for i in range(np.max(data.shape)):
                            sliced_data = slice_from_center(data,i,i,i)
                            if total - np.sum(sliced_data) < 0.1:
                                return sliced_data
                        return None

                    d = {
                        "data": find_encompassing_vol(shifted_data),
                        "shift": shift,
                        "dim": self.chgcar.dim
                    }
                    atomic_densities.append(d)
                self.atomic_densities = atomic_densities
Exemple #41
0
 def from_file(filename):
     cc = Chgcar.from_file(filename)
     return Pathfinder(cc)