def __init__(self, spg_number, mesh=None, tmax=None, is_sqs=False, is_average_mass=False, dim_sqs=None, prior_primitive_axis=None, band_points=None, poscar_name="POSCAR", magmom_line=None, mode_mean_masses="a", is_primitive=False, is_fct=False, is_bcm=False, variables=None, nac=None): if variables is None: self._dos_input = { "f_min": -10.0, # THz "f_max": 15.0, # THz "d_freq": 0.01, # THz "sigma": 0.1, # THz } else: self._dos_input = variables if mesh is None: mesh = [1, 1, 1] if dim_sqs is None: dim_sqs = [1, 1, 1] self._dictionary = {} self._poscar = Poscar(poscar_name) self._mesh = mesh self._tmax = tmax self._band_points = band_points self._spg_number = spg_number self._is_sqs = is_sqs self._is_average_mass = is_average_mass self._dim_sqs = dim_sqs self._is_primitive = is_primitive self._is_fct = is_fct self._is_bcm = is_bcm self._prior_primitive_axis = prior_primitive_axis self._mode_mean_masses = mode_mean_masses self._magmom_line = magmom_line self._nac = nac self._dim = get_dim('writefc.conf')
def convert_structure(): poscar = Poscar(getcwd()) poscar.title = 'Converted from B1 to B3' sc = poscar.supercell supercell_x = int(raw_input("Supercells in x-direction: ")) supercell_y = int(raw_input("Supercells in y-direction: ")) supercell_z = int(raw_input("Supercells in z-direction: ")) direction = raw_input("111 direction?: ") for atom in sc.atoms: if atom.symbol == 'N': if direction in ("Y", "y", "yes", "Yes", "YES"): atom.position[2] = atom.position[2] - 0.25/supercell_z else: atom.position[0] = atom.position[0] - 0.25/supercell_x atom.position[1] = atom.position[1] - 0.25/supercell_y atom.position[2] = atom.position[2] - 0.25/supercell_z poscar.create_file()
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')
def create_spg_number(self): """ spg_number is used to determine the primitive axis and band paths. """ if self._poscar_average_filename is not None: poscar_filename = self._poscar_average_filename else: poscar_filename = self._poscar_filename print('SPG number is searched from {}'.format(poscar_filename)) spg_number = Poscar(poscar_filename).get_symmetry_dataset()["number"] print("spg_number:", spg_number) return spg_number
def create_randomized_configurations(mapfile, infile, random_seed, numconf, is_sorted): """ Parameters ---------- mapfile : String Input file including mapping information. infile : String POSCAR filename. """ import json from vasp.poscar import Poscar from collections import OrderedDict atoms = Poscar(infile).get_atoms() with open(mapfile, "r") as f: map_s2s = json.load(f, object_pairs_hook=OrderedDict) order = create_order_of_symbols(map_s2s) configuration_randomizer = ConfigurationRandomizer( atoms=atoms, map_s2s=map_s2s, random_seed=random_seed, ) for i in range(numconf): atoms = configuration_randomizer.create_randomized_configuration() filename = "RPOSCAR-{}".format(i + 1) poscar = Poscar().set_atoms(atoms) if is_sorted: poscar.sort_by_symbols(order=order) poscar.write(filename)
def main(): """ The main function. Extracts the data specified in the input arguments. If no argument is given the default is to get all data. If a path is given, that will be used as the current directory. """ current_path = getcwd() if len(sys.argv) == 1: sys.argv = sys.argv + ['kpoints', 'kpoint_type', 'total_kpoints', 'title', 'formula_unit', 'total_energy', 'all_energies', 'total_cpu_time', 'encut', 'surface_area', 'print', 'dos'] elif isdir(sys.argv[1]): current_path = sys.argv[1] rf = open('%s/results.csv' % current_path, 'wb') result_csv_file = writer(rf, delimiter=',', quotechar='|', quoting=QUOTE_MINIMAL) written_header = False paths = Find(current_path, 'OUTCAR') for path in paths: if outcar_is_needed(): outcar = Outcar(path) if oszicar_is_needed(): oszicar = Oszicar(path) if poscar_is_needed(): poscar = Poscar(path) if contcar_is_needed(): contcar = Contcar(path) if kpoints_is_needed(): kpoints = Kpoints(path, extract=True) if doscar_is_needed(): doscar = Doscar(path) results = [] col_titles = [] for argument in sys.argv: if argument == 'title': if 'Title' not in col_titles: col_titles.append('Title') results.append(contcar.title) elif argument == 'lattice_constant': if 'a0 [Ang]' not in col_titles: col_titles.append('a0 [Ang]') results.append(contcar.supercell.a0) elif argument == 'coa': if 'c/a' not in col_titles: col_titles.append('c/a') try: results.append(contcar.coa) except: print contcar.path elif argument == 'average_u': if '<u>' not in col_titles: col_titles.append('<u>') results.append(contcar.calculate_average_u()) elif argument == 'surface_area': if 'Surface Area [Ang^2]' not in col_titles: col_titles.append('Surface Area [Ang^2]') results.append(contcar.surface_area) elif argument == 'formula_unit': if 'Formula unit' not in col_titles: col_titles.append('Formula unit') results.append(contcar.formula_unit) elif argument == 'adatom_pos': found = False if 'adatom_pos' not in col_titles: col_titles += ['adatom x', 'adatom y', 'adatom z'] try: contcar.find_adatoms() for atom in contcar.supercell.atoms: if atom.adatom: if 'real' in sys.argv: results += list(contcar.supercell.convert_to_real(atom.position)) else: results += list(atom.position) found = True break except: print "Error: No CONTCAR found, trying POSCAR instead!" if not found: try: poscar.find_adatoms() for atom in poscar.supercell.atoms: if atom.adatom: if 'real' in sys.argv: results += list(poscar.supercell.convert_to_real(atom.position)) else: results += list(atom.position) break except: print "Error: No POSCAR found either!" elif argument == 'old_adatom_pos': if 'old_adatom_pos' not in col_titles: col_titles += ['old-adatom x', 'old-adatom y', 'old-adatom z'] poscar.find_adatoms() for atom in poscar.supercell.atoms: if atom.adatom: if 'real' in sys.argv: results += list(poscar.supercell.convert_to_real(atom.position)) else: results += list(atom.position) break elif argument == 'total_energy': if 'Total Energy [eV]' not in col_titles: col_titles.append('Total Energy [eV]') results.append(oszicar.total_energy) elif argument == 'magmom': if 'Magmom' not in col_titles: col_titles.append('Magmom') results.append(oszicar.magmom) elif argument == 'all_energies': f = open('%s/all_energies.csv' % current_path, 'wb') energy_csv_file = writer(f, delimiter=',', quotechar='|', quoting=QUOTE_MINIMAL) energy_csv_file.writerow([contcar.title] + oszicar.all_energies) f.close() elif argument == 'nodes': if 'Nodes' not in col_titles: col_titles.append('Nodes') results.append(outcar.nodes) elif argument == 'total_cpu_time': if 'Total CPU time' not in col_titles: col_titles.append('Total CPU time') results.append(outcar.total_cpu_time) elif argument == 'volume': if 'Volume [Ang^3]' not in col_titles: col_titles.append('Volume [Ang^3]') results.append(outcar.volume) elif argument == 'total_nr_of_ions': if 'Nr of ions' not in col_titles: col_titles.append('Nr of ions') results.append(outcar.total_nr_of_ions) elif argument == 'kpoints': if 'K-points' not in col_titles: col_titles.append('K-points') results.append("%ix%ix%i" % outcar.kpoints) elif argument == 'total_kpoints': if 'Total K-points' not in col_titles: col_titles.append('Total K-points') results.append(outcar.total_kpoints) elif argument == 'nkpts': if 'Total K-points' not in col_titles: col_titles.append('NKPTS') results.append(outcar.nkpts) elif argument == 'kpoint_type': if 'K-mesh type' not in col_titles: col_titles.append('K-mesh type') results.append(kpoints.mesh_type) elif argument == 'encut': if 'ENCUT' not in col_titles: col_titles.append('ENCUT') results.append(outcar.encut) elif argument == 'bandgap': if 'Bandgap [eV]' not in col_titles: col_titles.append('Bandgap [eV]') results.append(doscar.bandgap) elif argument == 'dos': f = open('%s/dos.csv' % current_path, 'w') f.write("Fermi level,Bandgap\n") f.write("%f,%f\n" % (doscar.fermi_level, doscar.bandgap)) f.write("Energy,DOS,Integrated DOS\n") for line in doscar.dos: f.write("%s,%s,%s\n" % (line[0], line[1], line[2])) f.close() elif argument == 'dos_per_atom': i = 0 line = 0 for count in contcar.counts: int_dos = [[0] * 3] * doscar.steps f = open('%s/dos%s.csv' % (current_path, outcar.atom_symbols[i]), 'w') dos_csv_file = writer(f, delimiter=',', quotechar='|', quoting=QUOTE_MINIMAL) dos_csv_file.writerow(['Symbol', 'Count']) dos_csv_file.writerow([outcar.atom_symbols[i], count]) for atom in range(line, line + count): for energy in range(0, doscar.steps): int_dos[energy] = [doscar.dos_per_atom[atom][energy][0], int_dos[energy][1] + doscar.dos_per_atom[atom][energy][4], int_dos[energy][2] + doscar.dos_per_atom[atom][energy][5]] dos_csv_file.writerow(['Energy', 'DOS', 'Integrated DOS']) for row in int_dos: dos_csv_file.writerow(row) f.close() line += count i += 1 # Choose correct symbol if not written_header: result_csv_file.writerow(col_titles) written_header = True result_csv_file.writerow(results) rf.close() if 'print' in sys.argv: system('/bin/cat "%s/results.csv"' % current_path)
def main(): """ The main function. Extracts the data specified in the input arguments. If no argument is given the default is to get all data. If a path is given, that will be used as the current directory. """ if "path=" in sys.argv[1]: current_path = sys.argv[1][5:] else: current_path = getcwd() print current_path if len(sys.argv) == 1: sys.argv = sys.argv + ['kpoints', 'kpoint_type', 'total_kpoints', 'title', 'formula_unit', 'total_energy', 'all_energies', 'total_cpu_time', 'encut', 'surface_area', 'print', 'dos'] elif isdir(sys.argv[1]): current_path = sys.argv[1] rf = open('%s/results.csv' % current_path, 'wb') result_csv_file = writer(rf, delimiter=',', quotechar='|', quoting=QUOTE_MINIMAL) written_header = False paths = Find(current_path, ['OUTCAR', 'OUTCAR.gz', 'OUTCAR.bz2']) for path in paths: if outcar_is_needed(): outcar = Outcar(path) if oszicar_is_needed(): oszicar = Oszicar(path) if poscar_is_needed(): poscar = Poscar(path) if contcar_is_needed(): contcar = Contcar(path) if kpoints_is_needed(): kpoints = Kpoints(path, extract=True) if doscar_is_needed(): doscar = Doscar(path) results = [] col_titles = [] for argument in sys.argv: if argument == 'title': if 'Title' not in col_titles: col_titles.append('Title') results.append(contcar.title) elif argument == 'lattice_constant' or argument =='alat': if 'a0 [Ang]' not in col_titles: col_titles.append('a0 [Ang]') results.append(contcar.supercell.a0) elif argument == 'coa': if 'c/a' not in col_titles: col_titles.append('c/a') try: results.append(contcar.coa) except: print contcar.path elif argument == 'average_u': if '<u>' not in col_titles: col_titles.append('<u>') results.append(contcar.calculate_average_u()) elif argument == 'surface_area': if 'Surface Area [Ang^2]' not in col_titles: col_titles.append('Surface Area [Ang^2]') results.append(contcar.surface_area) elif argument == 'formula_unit': if 'Formula unit' not in col_titles: col_titles.append('Formula unit') results.append(contcar.formula_unit) elif argument == 'adatom_pos': found = False if 'adatom_pos' not in col_titles: col_titles += ['adatom x', 'adatom y', 'adatom z'] try: contcar.find_adatoms() for atom in contcar.supercell.atoms: if atom.adatom: if 'real' in sys.argv: results += list(contcar.supercell.convert_to_real(atom.position)) else: results += list(atom.position) found = True break except: print "Error: No CONTCAR found, trying POSCAR instead!" if not found: try: poscar.find_adatoms() for atom in poscar.supercell.atoms: if atom.adatom: if 'real' in sys.argv: results += list(poscar.supercell.convert_to_real(atom.position)) else: results += list(atom.position) break except: print "Error: No POSCAR found either!" elif argument == 'old_adatom_pos': if 'old_adatom_pos' not in col_titles: col_titles += ['old-adatom x', 'old-adatom y', 'old-adatom z'] poscar.find_adatoms() for atom in poscar.supercell.atoms: if atom.adatom: if 'real' in sys.argv: results += list(poscar.supercell.convert_to_real(atom.position)) else: results += list(atom.position) break elif argument == 'total_energy': if 'Total Energy [eV]' not in col_titles: col_titles.append('Total Energy [eV]') results.append(oszicar.total_energy) elif argument == 'magmom': if 'Magmom' not in col_titles: col_titles.append('Magmom') results.append(oszicar.magmom) elif argument == 'all_energies': f = open('%s/all_energies.csv' % current_path, 'wb') energy_csv_file = writer(f, delimiter=',', quotechar='|', quoting=QUOTE_MINIMAL) energy_csv_file.writerow([contcar.title] + oszicar.all_energies) f.close() elif argument == 'nodes': if 'Nodes' not in col_titles: col_titles.append('Nodes') results.append(outcar.nodes) elif argument == 'total_cpu_time': if 'Total CPU time' not in col_titles: col_titles.append('Total CPU time') results.append(outcar.total_cpu_time) elif argument == 'volume': if 'Volume [Ang^3]' not in col_titles: col_titles.append('Volume [Ang^3]') results.append(outcar.volume) elif argument == 'total_nr_of_ions': if 'Nr of ions' not in col_titles: col_titles.append('Nr of ions') results.append(outcar.total_nr_of_ions) elif argument == 'kpoints': if 'K-points' not in col_titles: col_titles.append('K-points') results.append("%ix%ix%i" % outcar.kpoints) elif argument == 'total_kpoints': if 'Total K-points' not in col_titles: col_titles.append('Total K-points') results.append(outcar.total_kpoints) elif argument == 'nkpts': if 'Total K-points' not in col_titles: col_titles.append('NKPTS') results.append(outcar.nkpts) elif argument == 'kpoint_type': if 'K-mesh type' not in col_titles: col_titles.append('K-mesh type') results.append(kpoints.mesh_type) elif argument == 'encut': if 'ENCUT' not in col_titles: col_titles.append('ENCUT') results.append(outcar.encut) elif argument == 'bandgap': if 'Bandgap [eV]' not in col_titles: col_titles.append('Bandgap [eV]') results.append(doscar.bandgap) elif argument == 'dos': f = open('%s/dos.csv' % current_path, 'w') f.write("Fermi level,Bandgap\n") f.write("%f,%f\n" % (doscar.fermi_level, doscar.bandgap)) f.write("Energy,DOS,Integrated DOS\n") for line in doscar.dos: f.write("%s,%s,%s\n" % (line[0], line[1], line[2])) f.close() elif argument == 'dos_per_atom': i = 0 line = 0 for count in contcar.counts: int_dos = [[0] * 3] * doscar.steps f = open('%s/dos%s.csv' % (current_path, outcar.atom_symbols[i]), 'w') dos_csv_file = writer(f, delimiter=',', quotechar='|', quoting=QUOTE_MINIMAL) dos_csv_file.writerow(['Symbol', 'Count']) dos_csv_file.writerow([outcar.atom_symbols[i], count]) for atom in range(line, line + count): for energy in range(0, doscar.steps): int_dos[energy] = [doscar.dos_per_atom[atom][energy][0], int_dos[energy][1] + doscar.dos_per_atom[atom][energy][4], int_dos[energy][2] + doscar.dos_per_atom[atom][energy][5]] dos_csv_file.writerow(['Energy', 'DOS', 'Integrated DOS']) for row in int_dos: dos_csv_file.writerow(row) f.close() line += count i += 1 # Choose correct symbol elif argument == 'polarization': if 'p_ionX' not in col_titles: col_titles = col_titles + ['p_ionX [eAng]', 'p_ionY [eAng]', 'p_ionZ [eAng]', 'p_elX [eAng]', 'p_elY [eAng]', 'p_elZ [eAng]'] results = results + outcar.polarization[0] + outcar.polarization[1] elif argument == 'ic_piezoelectric_tensor': f = open('%s/ic_piezoelectric_tensor.csv' % current_path, 'w') f.write('Ion-clamped Piezoelectric tensor [C/m^2]\n') pt = outcar.ic_piezo_tensor() f.write('XX,YY,ZZ,XY,YZ,ZX\n') for item in pt[0]: f.write(str(item) + ',') f.write('\n') for item in pt[1]: f.write(str(item) + ',') f.write('\n') for item in pt[2]: f.write(str(item) + ',') f.write('\n') f.close() elif argument == 'ci_e33': if 'CI e33' not in col_titles: col_titles.append('CI e33') results.append(outcar.ci_e33) elif argument == 'bc_33_average': if 'Born EC 33 [e]' not in col_titles: col_titles.append('Born EC 33 [e]') results.append(outcar.born_charge_33_average) elif argument == 'iterations': if 'Iterations' not in col_titles: col_titles.append('Iterations') results.append(oszicar.iterations) elif argument == 'permittivity': f = open('%s/permittivity.csv' % current_path, 'w') f.write('MACROSCOPIC STATIC DIELECTRIC TENSOR (including local field effects in DFT)\n') permittivity = outcar.permittivity f.write('X,Y,Z\n') for item in permittivity[0]: f.write(str(item) + ',') f.write('\n') for item in permittivity[1]: f.write(str(item) + ',') f.write('\n') for item in permittivity[2]: f.write(str(item) + ',') f.write('\n') f.close() if not written_header: result_csv_file.writerow(col_titles) written_header = True result_csv_file.writerow(results) rf.close() if 'print' in sys.argv: system('column -s, -t "%s/results.csv"' % current_path)
class PhonopyConfCreator(object): def __init__(self, spg_number, mesh=None, tmax=None, is_sqs=False, is_average_mass=False, dim_sqs=None, prior_primitive_axis=None, band_points=None, poscar_name="POSCAR", magmom_line=None, mode_mean_masses="a", is_primitive=False, is_fct=False, is_bcm=False, variables=None, nac=None): if variables is None: self._dos_input = { "f_min": -10.0, # THz "f_max": 15.0, # THz "d_freq": 0.01, # THz "sigma": 0.1, # THz } else: self._dos_input = variables if mesh is None: mesh = [1, 1, 1] if dim_sqs is None: dim_sqs = [1, 1, 1] self._dictionary = {} self._poscar = Poscar(poscar_name) self._mesh = mesh self._tmax = tmax self._band_points = band_points self._spg_number = spg_number self._is_sqs = is_sqs self._is_average_mass = is_average_mass self._dim_sqs = dim_sqs self._is_primitive = is_primitive self._is_fct = is_fct self._is_bcm = is_bcm self._prior_primitive_axis = prior_primitive_axis self._mode_mean_masses = mode_mean_masses self._magmom_line = magmom_line self._nac = nac self._dim = get_dim('writefc.conf') def run(self): self.generate_primitive_axis() print("primitive_axis:") print(self._primitive_axis) if self._is_sqs: self._primitive_axis = convert_primitive_axis(self._primitive_axis, dim=self._dim_sqs) primitive_axis_string = write_primitive_axis(self._primitive_axis) self._dictionary.update({ "DIM": (" {:d}" * len(self._dim)).format(*self._dim), "PRIMITIVE_AXIS": primitive_axis_string, "FORCE_CONSTANTS": "READ", }) if self._magmom_line is not None: self._dictionary["MAGMOM"] = self._magmom_line.strip() if self._is_average_mass: self.create_average_masses(self._poscar) if self._nac is not None: self._dictionary["NAC"] = ".TRUE." self._dictionary["NAC_METHOD"] = self._nac # "GONZE" or "WANG" self.generate_dictionary_dictionary() self.write() def create_average_masses(self, poscar): ncell = 1.0 / np.linalg.det(self._primitive_axis) ncell = int(round(ncell)) print("ncell:", ncell) natoms = poscar.get_atoms().get_number_of_atoms() natoms_in_primitive = natoms / ncell chemical_symbols = poscar.get_atoms().get_chemical_symbols() masses = get_average_masses(chemical_symbols, mode=self._mode_mean_masses) print("masses:") print(masses) self._dictionary.update({ "MASS": (" {:.16f}" * natoms_in_primitive).format(*masses[:natoms_in_primitive]) }) def generate_dictionary_dictionary(self): lattice_constants = self._poscar.get_dictionary() band = BandPath(self._spg_number, lattice_constants) band_path, band_labels = band.get_band_phonopy() variables = self._dos_input dos_range_string = "{} {} {}".format(variables["f_min"], variables["f_max"], variables["d_freq"]) self._dictionary_dictionary = { "band.conf": self._dictionary.copy(), "eigenvectors.conf": self._dictionary.copy(), "tprop.conf": self._dictionary.copy(), "dos_tetrahedron.conf": self._dictionary.copy(), "partial_dos_tetrahedron.conf": self._dictionary.copy(), "dos_smearing.conf": self._dictionary.copy(), "partial_dos_smearing.conf": self._dictionary.copy(), } self._dictionary_dictionary["band.conf"].update({ "BAND": band_path, "BAND_LABELS": band_labels, }) if self._band_points is not None: self._dictionary_dictionary["band.conf"].update( {"BAND_POINTS": "{:d}".format(self._band_points)}) self._dictionary_dictionary["eigenvectors.conf"].update({ "EIGENVECTORS": ".TRUE.", "BAND": band_path, "BAND_LABELS": band_labels, "BAND_POINTS": "2", }) self._dictionary_dictionary["tprop.conf"].update({ "MP": " {:d} {:d} {:d}".format(*self._mesh), "GAMMA_CENTER": ".TRUE.", "TPROP": ".TRUE.", "TMAX": "{:d}".format(self._tmax), }) self._dictionary_dictionary["dos_tetrahedron.conf"].update({ "MP": " {:d} {:d} {:d}".format(*self._mesh), "GAMMA_CENTER": ".TRUE.", "DOS": ".TRUE.", "DOS_RANGE": " {}".format(dos_range_string), "TETRAHEDRON": ".TRUE.", }) self._dictionary_dictionary["partial_dos_tetrahedron.conf"].update({ "MP": " {:d} {:d} {:d}".format(*self._mesh), "GAMMA_CENTER": ".TRUE.", "WRITE_MESH": ".FALSE.", "DOS": ".TRUE.", "DOS_RANGE": " {}".format(dos_range_string), "TETRAHEDRON": ".TRUE.", "PDOS": "", }) self._dictionary_dictionary["dos_smearing.conf"].update({ "MP": " {:d} {:d} {:d}".format(*self._mesh), "GAMMA_CENTER": ".TRUE.", "DOS": ".TRUE.", "DOS_RANGE": " {}".format(dos_range_string), "SIGMA": " {}".format(variables["sigma"]), }) self._dictionary_dictionary["partial_dos_smearing.conf"].update({ "MP": " {:d} {:d} {:d}".format(*self._mesh), "GAMMA_CENTER": ".TRUE.", "WRITE_MESH": ".FALSE.", "DOS": ".TRUE.", "DOS_RANGE": " {}".format(dos_range_string), "SIGMA": " {}".format(variables["sigma"]), "PDOS": "", }) def generate_primitive_axis(self): if self._is_primitive: primitive_axis = [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0], ] primitive_axis = np.array(primitive_axis) else: primitive_axis = PrimitiveAxis( spg_number=self._spg_number, is_fct=self._is_fct, is_bcm=self._is_bcm).get_primitive_axis() self._primitive_axis = primitive_axis def update(self, dictionary): self._dictionary.update(dictionary) def write(self): for filename, dictionary in self._dictionary_dictionary.items(): write_phonopy_conf(dictionary, filename)
def write_cell_enlarged_ideal(self, filename): poscar = Poscar() poscar.set_atoms(self._enlarged_cell_average) poscar.write(filename)
def write_cell_enlarged(self, filename): poscar = Poscar() poscar.set_atoms(self._enlarged_cell) poscar.write(filename)
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
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