def extrema_coords(volumetric_data: VolumetricData, find_min: bool, params: VolumetricDataAnalyzeParams) -> DataFrame: result = ChargeDensityAnalyzer(chgcar=volumetric_data) result.get_local_extrema(threshold_frac=params.threshold_frac, threshold_abs=params.threshold_abs, find_min=find_min) if params.min_dist: # Remove sites near host atoms. result.remove_collisions(params.min_dist) if params.tol: try: # Cluster interstitials that are too close together using a tol. result.cluster_nodes(tol=params.tol) except ValueError: # error raised when only a single local extreme point. pass if params.radius: result.sort_sites_by_integrated_chg(r=params.radius) result = result.extrema_df if "avg_charge_den" in result.columns: result.rename(columns={'avg_charge_den': 'ave_value'}, inplace=True) result.rename(columns={'Charge Density': 'value'}, inplace=True) logger.info("\n" + result.__str__()) return result
def interstitials_from_volumetric_data(volumetric_data: VolumetricData, find_min: bool = True, threshold_frac: float = None, threshold_abs: float = None, min_dist: float = 0.5, tol: float = 0.5, radius: float = 0.4) -> None: cda = ChargeDensityAnalyzer(chgcar=volumetric_data) cda.get_local_extrema(threshold_frac=threshold_frac, threshold_abs=threshold_abs, find_min=find_min) cda.sort_sites_by_integrated_chg(r=radius) # Remove sites near host atoms. cda.remove_collisions(min_dist) # Cluster interstitials that are too close together using a tol. try: cda.cluster_nodes(tol=tol) except ValueError: # error raised when only a single local extreme point. pass print(cda.extrema_df) structure: Structure = volumetric_data.structure.copy() start_index = len(structure) end_index = len(structure) + len(cda.extrema_coords) interstitial_indices = [i for i in range(start_index, end_index)] for coords in cda.extrema_coords: structure.append(Element.H, coords) symmetrizer = StructureSymmetrizer(structure) equiv_atoms = symmetrizer.spglib_sym_data["equivalent_atoms"] print(f"Host symmetry {symmetrizer.spglib_sym_data['international']}") print("++ Inequivalent indices and site symmetries ++") orig_num_atoms = len(volumetric_data.structure) structure_for_visualize: Structure = volumetric_data.structure.copy() for i, ii in enumerate(interstitial_indices): if ii == equiv_atoms[ii]: idx = orig_num_atoms + i coords = structure[idx].frac_coords def element(): for z in range(1, 100): e = Element.from_Z(z) if e not in structure_for_visualize.composition: yield e structure_for_visualize.append(next(element()), coords) idx_coords = \ f"{i:>3} {coords[0]:8.4f} {coords[1]:8.4f} {coords[2]:8.4f}" print(idx_coords, symmetrizer.spglib_sym_data["site_symmetry_symbols"][ii]) structure_for_visualize.to(filename="POSCAR-w-interstitials")
def test_cluster_nodes(self): ca = ChargeDensityAnalyzer(self.chg_FePO4) ca.get_local_extrema() ca.cluster_nodes(tol=20) self.assertEqual(len(ca.extrema_df), 1)