def run(self): """ For disordered systems with relaxed atomic positions, it might be better to use initial atomic positions to use the symmetry of the structure (POSCAR_initial). """ poscar = Poscar('POSCAR') number_of_atoms = poscar.get_atoms().get_number_of_atoms() dummy_symbols = self.create_dummy_symbols(number_of_atoms) poscar.get_atoms().set_chemical_symbols(dummy_symbols) poscar.write_poscar('POSCAR_ideal')
class FCReducer(object): def __init__(self, poscar_filename="POSCAR", fc_filename="FORCE_CONSTANTS"): self._poscar = Poscar(poscar_filename) self._force_constants = parse_FORCE_CONSTANTS(fc_filename) self._fc_reduced = None def find_indices_from_positions(self, positions): """Find atomic indices for removed FCs""" poscar = self._poscar indices_all = [] for position_combination in positions: indices_combination = [] for p in position_combination: index = poscar.get_index_from_position(p) indices_combination.append(index) indices_all.append(indices_combination) indices_all = np.array(indices_all) return indices_all def write(self, filename): write_FORCE_CONSTANTS(self._fc_reduced, filename=filename) def do_postprocess(self): poscar = self._poscar fc_analyzer = FCAnalyzerBase( atoms=poscar.get_atoms(), force_constants=self._fc_reduced, is_symmetrized=False, ) fc_analyzer.force_translational_invariance() self._fc_reduced = fc_analyzer.get_force_constants() def keep_FCs_for_positions(self, positions): """ Parameters ---------- positions: n x 2 x 3 array positions = np.array([ [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ]) """ poscar = self._poscar force_constants_orig = self._force_constants force_constants = np.zeros_like(force_constants_orig) positions = np.array(positions) indices_all = self.find_indices_from_positions(positions) print('indices_all:', indices_all) mappings = poscar.get_mappings_for_symops() for mapping in mappings: for indices_combination in indices_all: indices_removed = mapping[indices_combination] i0 = indices_removed[0] i1 = indices_removed[1] force_constants[i0, i1] = force_constants_orig[i0, i1] force_constants[i1, i0] = force_constants_orig[i1, i0] self._fc_reduced = force_constants self.do_postprocess() def remove_FCs_for_positions(self, positions): """ Parameters ---------- positions: n x 2 x 3 array positions = np.array([ [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ]) """ poscar = self._poscar force_constants = np.copy(self._force_constants) positions = np.array(positions) indices_all = self.find_indices_from_positions(positions) print('indices_all:', indices_all) mappings = poscar.get_mappings_for_symops() for mapping in mappings: for indices_combination in indices_all: indices_removed = mapping[indices_combination] i0 = indices_removed[0] i1 = indices_removed[1] force_constants[i0, i1] = 0.0 force_constants[i1, i0] = 0.0 self._fc_reduced = force_constants self.do_postprocess() def average_FCs_for_positions(self, positions): """ Parameters ---------- positions: n x 2 x 3 array positions = np.array([ [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], ]) """ poscar = self._poscar force_constants = np.copy(self._force_constants) force_constants_spg = self._create_fc_symmetrized_spg() positions = np.array(positions) indices_all = self.find_indices_from_positions(positions) print('indices_all:', indices_all) mappings = poscar.get_mappings_for_symops() for mapping in mappings: for indices_combination in indices_all: indices_removed = mapping[indices_combination] i0 = indices_removed[0] i1 = indices_removed[1] force_constants[i0, i1] = force_constants_spg[i0, i1] force_constants[i1, i0] = force_constants_spg[i1, i0] self._fc_reduced = force_constants self.do_postprocess() def _create_fc_symmetrized_spg(self): from .fc_symmetrizer_spg import FCSymmetrizerSPG force_constants = self._force_constants atoms_ideal = self._poscar.get_atoms() fc_symmetrizer_spg = FCSymmetrizerSPG(force_constants=force_constants, atoms=atoms_ideal, atoms_ideal=atoms_ideal, is_symmetrized=False) fc_symmetrizer_spg.average_force_constants_spg() fc_spg = fc_symmetrizer_spg.get_force_constants_symmetrized() return fc_spg