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()
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
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)
def from_file(filename): (poscar, data, data_aug) = VolumetricData.parse_file(filename) return CHGCAR(poscar, data, data_aug=data_aug)
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_)