def _get_chg_between_sites_tube(self,
                                    migration_hop,
                                    mask_file_seedname=None):
        """
        Calculate the amount of charge that a migrating ion has to move through in order to complete a hop
        Args:
            migration_hop: MigrationHop object that represents a given hop
            mask_file_seedname(string): seedname for output of the migration path masks (for debugging and
                visualization) (Default value = None)
        Returns:
            float: The total charge density in a tube that connects two sites of a given edges of the graph
        """
        try:
            self._tube_radius
        except NameError:
            logger.warning(
                "The radius of the tubes for charge analysis need to be defined first."
            )
        ipos = migration_hop.isite.frac_coords
        epos = migration_hop.esite.frac_coords

        cart_ipos = np.dot(ipos, self.potential_field.structure.lattice.matrix)
        cart_epos = np.dot(epos, self.potential_field.structure.lattice.matrix)
        pbc_mask = np.zeros(self._uc_grid_shape, dtype=bool).flatten()
        for img in self._images:
            grid_pos = np.dot(self._fcoords + img,
                              self.potential_field.structure.lattice.matrix)
            proj_on_line = np.dot(
                grid_pos - cart_ipos, cart_epos -
                cart_ipos) / (np.linalg.norm(cart_epos - cart_ipos))
            dist_to_line = np.linalg.norm(
                np.cross(grid_pos - cart_ipos, cart_epos - cart_ipos) /
                (np.linalg.norm(cart_epos - cart_ipos)),
                axis=-1,
            )

            mask = ((proj_on_line >= 0) *
                    (proj_on_line < np.linalg.norm(cart_epos - cart_ipos)) *
                    (dist_to_line < self._tube_radius))
            pbc_mask = pbc_mask + mask
        pbc_mask = pbc_mask.reshape(self._uc_grid_shape)

        if mask_file_seedname:
            mask_out = VolumetricData(
                structure=self.potential_field.structure.copy(),
                data={"total": self.potential_field.data["total"]},
            )
            mask_out.structure.insert(0, "X", ipos)
            mask_out.structure.insert(0, "X", epos)
            mask_out.data[self.potential_data_key] = pbc_mask
            isym = self.symm_structure.wyckoff_symbols[migration_hop.iindex]
            esym = self.symm_structure.wyckoff_symbols[migration_hop.eindex]
            mask_out.write_file(
                f"{mask_file_seedname}_{isym}_{esym}_tot({mask_out.data[self.potential_data_key].sum():.2f}).vasp"
            )

        return (
            self.potential_field.data[self.potential_data_key][pbc_mask].sum()
            / self.potential_field.ngridpts /
            self.potential_field.structure.volume)
def test_make_local_extrema(tmpdir, mocker, simple_cubic):
    print(tmpdir)
    tmpdir.chdir()

    mock_params = mocker.patch(
        "pydefect.cli.vasp.main_vasp_functions.VolumetricDataAnalyzeParams")
    mock_make_extrema = mocker.patch(
        "pydefect.cli.vasp.main_vasp_functions.make_local_extrema_from_volumetric_data"
    )
    volumetric_data = VolumetricData(simple_cubic,
                                     data={"total": np.array([[[0.0]]])})
    args = Namespace(volumetric_data=[volumetric_data],
                     find_max=True,
                     info="a",
                     threshold_frac=None,
                     threshold_abs=None,
                     min_dist=0.1,
                     tol=0.2,
                     radius=0.3)
    make_local_extrema(args)
    mock_params.assert_called_once_with(None, None, 0.1, 0.2, 0.3)
    mock_make_extrema.assert_called_once_with(volumetric_data=volumetric_data,
                                              params=mock_params.return_value,
                                              info="a",
                                              find_min=False)
    mock_make_extrema.return_value.to_json_file.assert_called_once_with()
Example #3
0
    def __init__(self,parchg_file):

        """
        Reads in the data from the provided PARCHG file and store as class attributes

        Parameters
        ----------
        parchg_file: (str) full path to PARCHG file

        """

        self.path, self.filename = os.path.split(parchg_file)

        if self.filename.endswith('.hdf5'):
            parchg = VolumetricData.from_hdf5(parchg_file)
        else:
            parchg = Chgcar.from_file(parchg_file)
            ## convert to hdf5 for much quicker reading in the future...
            Chgcar.from_file(parchg_file).to_hdf5(os.path.join(self.path,'%s.hdf5'%self.filename))

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

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

        ## grid size (NGXF, NGYF, NGZF)
        (self.ngrid_a, self.ngrid_b, self.ngrid_c) = np.shape(self.chgdata)

        ## grid vectors
        self.gridvec_a = self.structure.lattice.matrix[0]/self.ngrid_a
        self.gridvec_b = self.structure.lattice.matrix[1]/self.ngrid_b
Example #4
0
def test_extrema_coords(vasp_files, simple_cubic, vol_params):
    aeccar = VolumetricData(simple_cubic,
                            data={
                                "total":
                                np.array([[[0.0, 0.0], [-1.0, 0.0]],
                                          [[-1.0, 0.0], [-2.0, -1.0]]])
                            })
    params = copy(vol_params)
    params.min_dist = 0.01
    params.radius = 0.51
    actual = extrema_coords(volumetric_data=aeccar,
                            find_min=True,
                            params=params)
    expected = DataFrame([[0.5, 0.5, 0.0, -2.0, -1.25]],
                         columns=["a", "b", "c", "value", "ave_value"])
    assert_frame_equal(actual, expected)
Example #5
0
 def from_file(filename):
     (poscar, data, data_aug) = VolumetricData.parse_file(filename)
     return CHGCAR(poscar, data, data_aug=data_aug)
Example #6
0
 def to_VolumetricData(self) -> VolumetricData:
     key_ = next(iter(self.chargeden_dict))
     struct = self.chargeden_dict[key_].structure
     data_ = {k: v.renormalized_data for k, v in self.chargeden_dict.items()}
     return VolumetricData(struct, data_)