def get_phonon_configs(calc, at, disps, scell, config_type): cell = PhonopyAtoms(symbols=at.get_chemical_symbols(), cell=at.get_cell(), positions=at.get_positions()) phonon = Phonopy(cell, np.eye(3) * scell) al = [] for disp in disps: print(disp, config_type) phonon.generate_displacements(distance=disp) supercells = phonon.get_supercells_with_displacements() for (i, scell) in enumerate(supercells): at = ase.Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True) at.set_calculator(calc) e = at.get_potential_energy() f = at.get_forces() v = -1.0 * at.get_volume() * at.get_stress(voigt=False) at.arrays["force"] = f at.info["virial"] = v at.info["config_type"] = "PH_" + config_type at.info["energy_TB"] = e #write("PH_{}_{}_scell_{}.xyz".format(config_type, i, disp), at) al.append(at) return al
def run_phonolammps(): n = 2 phlammps = Phonolammps('in.graphene', supercell_matrix=[[n, 0, 0], [0, n, 0], [0, 0, n]]) unitcell = phlammps.get_unitcell() force_constants = phlammps.get_force_constants() supercell_matrix = phlammps.get_supercell_matrix() print('unitcell') print('*' * 50) print(unitcell) print('force const') print('*' * 50) print(force_constants) print('supercell') print('*' * 50) print(supercell_matrix) from phonopy import Phonopy phonon = Phonopy(unitcell, supercell_matrix) print(phonon) print(dir(phonon)) phonon.set_force_constants(force_constants) phonon.set_mesh([20, 20, 20]) # phonon.write_yaml_band_structure('band.conf') # phonon.set_band_structure('band.conf') # phonon.plot_band_structure().savefig('band.png') # phonon.set_total_DOS() # phonon.plot_total_DOS().savefig('dos.png') phonon.set_thermal_properties() # print(phonon.get_thermal_properties_dict()) phonon.plot_thermal_properties().savefig('therm.png')
def setup(self): phonon = Phonopy(self._bulk, supercell_matrix=[[6, 0, 0], [0, 6, 0], [0, 0, 6]]) self._phonon = phonon self._symmetry = self._phonon.get_symmetry() self._force_sets = parse_FORCE_SETS() phonon.get_displacement_dataset()
def get_force_sets_inline(**kwargs): from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import Phonopy structure = kwargs.pop('structure') phonopy_input = kwargs.pop('phonopy_input').get_dict() # Generate phonopy phonon object bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites], positions=[site.position for site in structure.sites], cell=structure.cell) phonon = Phonopy(bulk, phonopy_input['supercell'], primitive_matrix=phonopy_input['primitive'], symprec=phonopy_input['symmetry_precision']) phonon.generate_displacements(distance=phonopy_input['distance']) # Build data_sets from forces of supercells with displacments data_sets = phonon.get_displacement_dataset() for i, first_atoms in enumerate(data_sets['first_atoms']): first_atoms['forces'] = kwargs.pop( 'force_{}'.format(i)).get_array('forces')[-1] data = ArrayData() data.set_array('force_sets', np.array(data_sets)) return {'phonopy_output': data}
def _get_supercell_phonon(self, ph_in): """Returns Phonopy instance of supercell as the primitive""" ph = Phonopy(ph_in.supercell, supercell_matrix=[1, 1, 1], primitive_matrix='P') fc_shape = ph_in.force_constants.shape if fc_shape[0] == fc_shape[1]: # assume full fc ph.force_constants = ph_in.force_constants.copy() else: ph.force_constants = compact_fc_to_full_fc(ph_in, ph_in.force_constants) if ph_in.nac_params: p2p = ph_in.primitive.p2p_map s2p = ph_in.primitive.s2p_map s2pp = [p2p[i] for i in s2p] born_in = ph_in.nac_params['born'] born = [born_in[i] for i in s2pp] nac_params = { 'born': np.array(born, dtype='double', order='C'), 'factor': ph_in.nac_params['factor'], 'dielectric': ph_in.nac_params['dielectric'].copy() } ph.nac_params = nac_params return ph
def create_supercells_with_displacements_inline(**kwargs): from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import Phonopy structure = kwargs.pop('structure') phonopy_input = kwargs.pop('phonopy_input').get_dict() # Generate phonopy phonon object bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites], positions=[site.position for site in structure.sites], cell=structure.cell) phonon = Phonopy(bulk, phonopy_input['supercell'], primitive_matrix=phonopy_input['primitive'], symprec=phonopy_input['symmetry_precision']) phonon.generate_displacements(distance=phonopy_input['distance']) cells_with_disp = phonon.get_supercells_with_displacements() # Transform cells to StructureData and set them ready to return disp_cells = {} for i, phonopy_supercell in enumerate(cells_with_disp): supercell = StructureData(cell=phonopy_supercell.get_cell()) for symbol, position in zip(phonopy_supercell.get_chemical_symbols(), phonopy_supercell.get_positions()): supercell.append_atom(position=position, symbols=symbol) disp_cells["structure_{}".format(i)] = supercell return disp_cells
def _get_supercell_phonon(self, ph_in): """Return Phonopy instance of supercell as the primitive.""" ph = Phonopy(ph_in.supercell, supercell_matrix=[1, 1, 1], primitive_matrix="P") fc_shape = ph_in.force_constants.shape if fc_shape[0] == fc_shape[1]: # assume full fc ph.force_constants = ph_in.force_constants.copy() else: ph.force_constants = compact_fc_to_full_fc(ph_in, ph_in.force_constants) if ph_in.nac_params: p2p = ph_in.primitive.p2p_map s2p = ph_in.primitive.s2p_map s2pp = [p2p[i] for i in s2p] born_in = ph_in.nac_params["born"] born = [born_in[i] for i in s2pp] nac_params = { "born": np.array(born, dtype="double", order="C"), "factor": ph_in.nac_params["factor"], "dielectric": ph_in.nac_params["dielectric"].copy(), } ph.nac_params = nac_params return ph
def __init__(self, model=None, structure=None, atom_disp=0.015, **kwargs): self.model = model self.structure = structure self.atom_disp = atom_disp self.qpoints, self.vertices = get_qpoints_and_vertices(self.structure) is_plusminus = kwargs.get('is_plusminus', True) is_diagonal = kwargs.get('is_diagonal', True) is_trigonal = kwargs.get('is_diagonal', False) supercell_matrix = kwargs.get('is_diagonal', None) ph_structure = get_phonopy_structure(self.structure) if supercell_matrix is None: supercell_matrix = np.eye(3) * np.array((1, 1, 1)) self.phonon = Phonopy(unitcell=ph_structure, supercell_matrix=supercell_matrix) self.phonon.generate_displacements(distance=self.atom_disp, is_plusminus=is_plusminus, is_diagonal=is_diagonal, is_trigonal=is_trigonal) disp_supercells = self.phonon.get_supercells_with_displacements() # Perfect supercell structure init_supercell = self.phonon.get_supercell() # Structure list to be returned self.structure_list = [get_pmg_structure(init_supercell)] for c in disp_supercells: if c is not None: self.structure_list.append(get_pmg_structure(c)) forces = self.model.calculate_forces(self.structure_list) self.phonon.set_forces(forces[1:]) self.phonon.produce_force_constants() logging.info("Force constant produced")
def test_nacl(ph_nacl: Phonopy): """Test displacements of NaCl 2x2x2.""" dataset = deepcopy(ph_nacl.dataset) disp_ref = [[0, 0.01, 0.0, 0.0], [32, 0.01, 0.0, 0.0]] np.testing.assert_allclose(ph_nacl.displacements, disp_ref, atol=1e-8) ph_nacl.generate_displacements() np.testing.assert_allclose(ph_nacl.displacements, disp_ref, atol=1e-8) ph_nacl.dataset = dataset
def test_si(ph_si: Phonopy): """Test displacements of Si.""" dataset = deepcopy(ph_si.dataset) disp_ref = [[0, 0.0, 0.0070710678118655, 0.0070710678118655]] np.testing.assert_allclose(ph_si.displacements, disp_ref, atol=1e-8) ph_si.generate_displacements() np.testing.assert_allclose(ph_si.displacements, disp_ref, atol=1e-8) ph_si.dataset = dataset
def _get_phonon(self, cell): phonon = Phonopy(cell, np.diag([1, 1, 1]), is_auto_displacements=False) force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() return phonon
def _get_phonon(spgtype, dim, pmat): cell = read_vasp(os.path.join(data_dir, "POSCAR_%s" % spgtype)) phonon = Phonopy(cell, np.diag(dim), primitive_matrix=pmat) force_sets = parse_FORCE_SETS( filename=os.path.join(data_dir, "FORCE_SETS_%s" % spgtype)) phonon.dataset = force_sets phonon.produce_force_constants() return phonon
def input_files(self, path_POSCAR, path_FORCECONSTANT): bulk = read_vasp(path_POSCAR) self.phonon = Phonopy(bulk, self.super_cell, primitive_matrix=self.primitive_cell) force_constants = file_IO.parse_FORCE_CONSTANTS(path_FORCECONSTANT) self.phonon.set_force_constants(force_constants) return self.phonon
def _get_phonon(self, spgtype, dim, pmat): cell = read_vasp(os.path.join(data_dir,"POSCAR_%s" % spgtype)) phonon = Phonopy(cell, np.diag(dim), primitive_matrix=pmat) force_sets = parse_FORCE_SETS(filename=os.path.join(data_dir,"FORCE_SETS_%s" % spgtype)) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() return phonon
def _enable_phonopy(self): if self.phonopy is None: if self.structure is not None: self.phonopy = Phonopy(unitcell=self._phonopy_unit_cell, supercell_matrix=self._phonopy_supercell_matrix(), factor=self.input['factor']) self.phonopy.generate_displacements(distance=self.input['displacement']) self.to_hdf() else: raise ValueError('No reference job/ No reference structure found.')
def get_force_constants_from_phonopy(structure, ph_settings, force_sets): """ Calculate the force constants locally using phonopy :param structure: :param phonopy_input: ParameterData object that contains phonopy settings :param force_sets: ForceSetsData object that contains the atomic forces and displacements info (datasets dict in phonopy) :return: ForceConstantsData object containing the 2nd order force constants calculated with phonopy """ from phonopy import Phonopy # Generate phonopy phonon object phonon = Phonopy(phonopy_bulk_from_structure(structure), ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_precision) phonon.generate_displacements(distance=ph_settings.dict.distance) # Build data_sets from forces of supercells with displacments phonon.set_displacement_dataset(force_sets.get_force_sets()) phonon.produce_force_constants() force_constants = ForceConstantsData(data=phonon.get_force_constants()) return {'force_constants': force_constants}
def obtain_eigenvectors_from_phonopy(structure, q_vector, NAC=False): # Checking data force_atoms_file = structure.get_force_set().item(0)["natom"] force_atoms_input = np.product(np.diagonal(structure.get_super_cell_phonon())) * structure.get_number_of_atoms() if force_atoms_file != force_atoms_input: print("Error: FORCE_SETS file does not match with SUPERCELL MATRIX") exit() # Preparing the bulk type object bulk = PhonopyAtoms( symbols=structure.get_atomic_types(), scaled_positions=structure.get_scaled_positions(), cell=structure.get_cell().T, ) phonon = Phonopy( bulk, structure.get_super_cell_phonon(), primitive_matrix=structure.get_primitive_matrix(), is_auto_displacements=False, ) # Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option] if NAC: print("Phonopy warning: Using Non Analytical Corrections") get_is_symmetry = True # from phonopy: settings.get_is_symmetry() primitive = phonon.get_primitive() nac_params = parse_BORN(primitive, get_is_symmetry) phonon.set_nac_params(nac_params=nac_params) phonon.set_displacement_dataset(copy.deepcopy(structure.get_force_set())) phonon.produce_force_constants() frequencies, eigenvectors = phonon.get_frequencies_with_eigenvectors(q_vector) # Making sure eigenvectors are orthonormal (can be omitted) if True: eigenvectors = eigenvectors_normalization(eigenvectors) print("Testing eigenvectors orthonormality") np.set_printoptions(precision=3, suppress=True) print(np.dot(eigenvectors.T, np.ma.conjugate(eigenvectors)).real) np.set_printoptions(suppress=False) # Arranging eigenvectors by atoms and dimensions number_of_dimensions = structure.get_number_of_dimensions() number_of_primitive_atoms = structure.get_number_of_primitive_atoms() arranged_ev = np.array( [ [ [eigenvectors[j * number_of_dimensions + k, i] for k in range(number_of_dimensions)] for j in range(number_of_primitive_atoms) ] for i in range(number_of_primitive_atoms * number_of_dimensions) ] ) return arranged_ev, frequencies
def _get_phonon(self, cell): phonon = Phonopy(cell, np.diag([2, 2, 2]), primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) force_sets = parse_FORCE_SETS(filename="FORCE_SETS_moment") phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() supercell = phonon.get_supercell() born_elems = {'Na': [[1.08703, 0, 0], [0, 1.08703, 0], [0, 0, 1.08703]], 'Cl': [[-1.08672, 0, 0], [0, -1.08672, 0], [0, 0, -1.08672]]} born = [born_elems[s] for s in ['Na', 'Cl']] epsilon = [[2.43533967, 0, 0], [0, 2.43533967, 0], [0, 0, 2.43533967]] factors = 14.400 phonon.set_nac_params({'born': born, 'factor': factors, 'dielectric': epsilon}) return phonon
def get_thermal_properties(structure, ph_settings, force_constants_list): from phonopy import Phonopy from aiida_phonopy.workchains.phonon import phonopy_bulk_from_structure free_energy_list = [] entropy_list = [] cv_list = [] temperature = None for fc in force_constants_list: phonon = Phonopy(phonopy_bulk_from_structure(structure), ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_precision) # Normalization factor primitive to unit cell normalization_factor = phonon.unitcell.get_number_of_atoms()/phonon.primitive.get_number_of_atoms() phonon.set_force_constants(fc) phonon.set_mesh(ph_settings.dict.mesh, is_eigenvectors=True, is_mesh_symmetry=False) phonon.set_thermal_properties() temperature, free_energy, entropy, cv = phonon.get_thermal_properties() free_energy_list.append(np.array(free_energy) * normalization_factor) entropy_list.append(np.array(entropy) * normalization_factor) cv_list.append(np.array(cv) * normalization_factor) return np.array(free_energy_list), np.array(entropy_list).T, np.array(cv_list).T, temperature
def _get_phonon(ph_in): ph = Phonopy(ph_in.supercell, supercell_matrix=[1, 1, 1]) ph.force_constants = ph_in.force_constants born_elems = { s: ph_in.nac_params['born'][i] for i, s in enumerate(ph_in.primitive.symbols) } born = [born_elems[s] for s in ph_in.supercell.symbols] epsilon = ph_in.nac_params['dielectric'] factors = ph_in.nac_params['factor'] ph.nac_params = {'born': born, 'factor': factors, 'dielectric': epsilon} return ph
def to_phonopy(self) -> Phonopy: if self.force_constants is None: raise ValueError("Set force_constants first.") _nac = "" if self.nac_params else "*not* " logger.info(f"Parameters for a non-analytical term correction are " f"{_nac}set.") result = Phonopy(unitcell=structure_to_phonopy_atoms(self.unitcell), supercell_matrix=self.supercell_matrix, nac_params=self.nac_params) result.force_constants = self.force_constants return result
def _get_phonon(ph_in): ph = Phonopy(ph_in.supercell, supercell_matrix=[1, 1, 1]) ph.force_constants = ph_in.force_constants born_elems = { s: ph_in.nac_params["born"][i] for i, s in enumerate(ph_in.primitive.symbols) } born = [born_elems[s] for s in ph_in.supercell.symbols] epsilon = ph_in.nac_params["dielectric"] factors = ph_in.nac_params["factor"] ph.nac_params = {"born": born, "factor": factors, "dielectric": epsilon} return ph
def get_phonon(pk, pk_nac): n = load_node(pk) unitcell = phonopy_atoms_from_structure(n.inputs.structure) smat = n.outputs.phonon_setting_info['supercell_matrix'] ph = Phonopy(unitcell, supercell_matrix=smat, primitive_matrix='auto') force_sets = n.outputs.force_sets.get_array('force_sets') dataset = n.outputs.phonon_setting_info['displacement_dataset'] ph.dataset = dataset ph.forces = force_sets ph.nac_params = get_nac_params(pk_nac) return ph
def phonopy_pre_process(cell, config_type, supercell_matrix=None): smat = [[3, 0, 0], [0, 3, 0], [0, 0, 3]] phonon = Phonopy(cell, smat) phonon.generate_displacements(distance=0.16) #0.02 print("[Phonopy] Atomic displacements:") disps = phonon.get_displacements() for d in disps: print("[Phonopy] %d %s" % (d[0], d[1:])) return phonon
def get_displaced_structures(pmg_structure, atom_disp=0.01, supercell_matrix=None, yaml_fname=None, **kwargs): """ Generate a set of symmetrically inequivalent displaced structures for phonon calculations. Args: pmg_structure (Structure): A pymatgen structure object. atom_disp (float): Atomic displacement. Default is 0.01 $\\AA$. supercell_matrix (3x3 array): Scaling matrix for supercell. yaml_fname (string): If not None, it represents the full path to the outputting displacement yaml file, e.g. disp.yaml. **kwargs: Parameters used in Phonopy.generate_displacement method. Return: A list of symmetrically inequivalent structures with displacements, in which the first element is the perfect supercell structure. """ is_plusminus = kwargs.get("is_plusminus", "auto") is_diagonal = kwargs.get("is_diagonal", True) is_trigonal = kwargs.get("is_trigonal", False) ph_structure = get_phonopy_structure(pmg_structure) if supercell_matrix is None: supercell_matrix = np.eye(3) * np.array((1, 1, 1)) phonon = Phonopy(unitcell=ph_structure, supercell_matrix=supercell_matrix) phonon.generate_displacements(distance=atom_disp, is_plusminus=is_plusminus, is_diagonal=is_diagonal, is_trigonal=is_trigonal) if yaml_fname is not None: displacements = phonon.get_displacements() directions = phonon.get_displacement_directions() write_disp_yaml(displacements=displacements, supercell=phonon.get_supercell(), directions=directions, filename=yaml_fname) # Supercell structures with displacement disp_supercells = phonon.get_supercells_with_displacements() # Perfect supercell structure init_supercell = phonon.get_supercell() # Structure list to be returned structure_list = [get_pmg_structure(init_supercell)] for c in disp_supercells: if c is not None: structure_list.append(get_pmg_structure(c)) return structure_list
def test_rand_FCM(self): fcm = ForceConstantMatrix( self.piezo_struc, self.FCM, self.pointops, self.sharedops ) fcm.get_FCM_operations() rand_FCM = fcm.get_rand_FCM() structure = pymatgen.io.phonopy.get_phonopy_structure(self.piezo_struc) pnstruc = Phonopy(structure, np.eye(3), np.eye(3)) pnstruc.set_force_constants(rand_FCM) dyn = pnstruc.get_dynamical_matrix_at_q([0, 0, 0]) dyn = np.reshape(dyn, (10, 3, 10, 3)).swapaxes(1, 2) dyn = np.real(dyn) numsites = len(self.piezo_struc) masses = [] for j in range(numsites): masses.append(self.piezo_struc.sites[j].specie.atomic_mass) dynmass = np.zeros([numsites, numsites, 3, 3]) for m in range(numsites): for n in range(numsites): dynmass[m][n] = dyn[m][n] / np.sqrt(masses[m]) / np.sqrt(masses[n]) dynmass = np.reshape(np.swapaxes(dynmass, 1, 2), (10 * 3, 10 * 3)) eigs, vecs = np.linalg.eig(dynmass) eigsort = np.argsort(np.abs(eigs)) for i in range(3, len(eigs)): self.assertTrue(eigs[eigsort[i]] < 1e-06) # rand_FCM1 = np.reshape(rand_FCM1, (10,3,10,3)).swapaxes(1,2) dynmass = np.reshape(dynmass, (10, 3, 10, 3)).swapaxes(1, 2) for i in range(len(self.FCM_operations)): for j in range(len(self.FCM_operations[i][4])): self.assertTrue( np.allclose( self.FCM_operations[i][4][j].transform_tensor( dynmass[self.FCM_operations[i][2]][ self.FCM_operations[i][3] ] ), dynmass[self.FCM_operations[i][0]][self.FCM_operations[i][1]], atol=1e-04, ) ) for i in range(len(dynmass)): asum1 = np.zeros([3, 3]) asum2 = np.zeros([3, 3]) for j in range(len(dynmass[i])): asum1 += dynmass[i][j] asum2 += dynmass[j][i] self.assertTrue(np.allclose(asum1, np.zeros([3, 3]), atol=1e-05)) self.assertTrue(np.allclose(asum2, np.zeros([3, 3]), atol=1e-05))
def get_data_from_dir(directory, i_volume): data_sets = file_IO.parse_FORCE_SETS( filename=directory + '/phonon-{0:02d}/FORCE_SETS'.format(i_volume)) yaml_file = open( directory + '/phonon-{0:02d}/phonon.yaml'.format(i_volume), 'r') data = yaml.load_all(yaml_file).next() unit_cell = PhonopyAtoms( symbols=[item['symbol'] for item in data['points']], scaled_positions=[item['coordinates'] for item in data['points']], cell=data['lattice']) phonon = Phonopy(unit_cell, data['supercell_matrix']) phonon.set_displacement_dataset(data_sets) phonon.produce_force_constants() force_constants = phonon.get_force_constants() supercell = phonon.get_supercell() volume = unit_cell.get_volume() energy = data['electric_total_energy'] return supercell, volume, energy, force_constants, data['supercell_matrix']
def read_phonopy(sposcar='SPOSCAR', sc_mat=np.eye(3), force_constants=None, disp_yaml=None, force_sets=None): if force_constants is None and (disp_yaml is None or force_sets is None): raise ValueError( "Either FORCE_CONSTANTS or (disp.yaml&FORCE_SETS) file should be provided." ) atoms = read(sposcar) #vesta_view(atoms) primitive_matrix = inv(sc_mat) bulk = PhonopyAtoms(symbols=atoms.get_chemical_symbols(), scaled_positions=atoms.get_scaled_positions(), cell=atoms.get_cell()) phonon = Phonopy( bulk, supercell_matrix=np.eye(3), primitive_matrix=primitive_matrix, #factor=factor, #symprec=symprec ) if disp_yaml is not None: disp = parse_disp_yaml(filename=disp_yaml) phonon.set_displacement_dataset(disp) if force_sets is not None: fc = parse_FORCE_SETS(filename=force_sets) phonon.set_forces(fc) fc = parse_FORCE_CONSTANTS(force_constants) phonon.set_force_constants(fc) return phonon
def _get_phonon(self, cell): phonon = Phonopy(cell, np.diag([2, 2, 2]), primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) force_sets = parse_FORCE_SETS(filename=os.path.join(data_dir,"FORCE_SETS_moment")) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() supercell = phonon.get_supercell() born_elems = {'Na': [[1.08703, 0, 0], [0, 1.08703, 0], [0, 0, 1.08703]], 'Cl': [[-1.08672, 0, 0], [0, -1.08672, 0], [0, 0, -1.08672]]} born = [born_elems[s] for s in ['Na', 'Cl']] epsilon = [[2.43533967, 0, 0], [0, 2.43533967, 0], [0, 0, 2.43533967]] factors = 14.400 phonon.set_nac_params({'born': born, 'factor': factors, 'dielectric': epsilon}) return phonon
def _get_phonon(self): cell = read_vasp(os.path.join(data_dir, "..", "POSCAR_NaCl")) phonon = Phonopy(cell, np.diag([2, 2, 2]), primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) filename = os.path.join(data_dir, "FORCE_SETS_NaCl") force_sets = parse_FORCE_SETS(filename=filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() born_elems = {'Na': [[1.08703, 0, 0], [0, 1.08703, 0], [0, 0, 1.08703]], 'Cl': [[-1.08672, 0, 0], [0, -1.08672, 0], [0, 0, -1.08672]]} born = [born_elems[s] for s in ['Na', 'Cl']] epsilon = [[2.43533967, 0, 0], [0, 2.43533967, 0], [0, 0, 2.43533967]] factors = 14.400 phonon.set_nac_params({'born': born, 'factor': factors, 'dielectric': epsilon}) return phonon
def get_rand_FCM(self, asum=15, force=10): """ Generate a symmeterized force constant matrix from an unsymmeterized matrix that has no unstable modes and also obeys the acoustic sum rule through an iterative procedure Args: force (float): maximum force constant asum (int): number of iterations to attempt to obey the acoustic sum rule Return: NxNx3x3 np.array representing the force constant matrix """ numsites = len(self.structure.sites) structure = pymatgen.io.phonopy.get_phonopy_structure(self.structure) pnstruc = Phonopy(structure, np.eye(3), np.eye(3)) dyn = self.get_unstable_FCM(force) dyn = self.get_stable_FCM(dyn) dyn = np.reshape(dyn, (numsites, 3, numsites, 3)).swapaxes(1, 2) dynmass = np.zeros([len(self.structure), len(self.structure), 3, 3]) masses = [] for j in range(numsites): masses.append(self.structure.sites[j].specie.atomic_mass) dynmass = np.zeros([numsites, numsites, 3, 3]) for m in range(numsites): for n in range(numsites): dynmass[m][n] = dyn[m][n] * np.sqrt(masses[m]) * np.sqrt( masses[n]) supercell = pnstruc.get_supercell() primitive = pnstruc.get_primitive() converter = dyntofc.DynmatToForceConstants(primitive, supercell) dyn = np.reshape(np.swapaxes(dynmass, 1, 2), (numsites * 3, numsites * 3)) converter.set_dynamical_matrices(dynmat=[dyn]) converter.run() fc = converter.get_force_constants() return fc
def get_f_vib_phonopy(structure, supercell_matrix, vasprun_path, qpoint_mesh=(50, 50, 50), t_min=5, t_step=5, t_max=2000.0,): """ Return F_vib(T) for the unitcell in eV/atom Parameters ---------- structure : pymatgen.Structure Unitcell (not supercell) of interest. supercell_matrix : numpy.ndarray 3x3 matrix of the supercell deformation, e.g. [[3, 0, 0], [0, 3, 0], [0, 0, 3]]. vasprun_path : str String pointing to a vasprun.xml file from a force constants run qpoint_mesh : list Mesh of q-points to calculate thermal properties on. t_min : float Minimum temperature t_step : float Temperature step size t_max : float Maximum temperature (inclusive) Returns ------- tuple Tuple of (temperature, F_vib, S_vib, Cv_vib, force_constants) """ # get codename and version from vasprun.xml file code_name, code_version = get_code_version(xml=vasprun_path) force_constant_factor = 1.0 if code_version[0:1] >= '6': force_constant_factor = 0.004091649655126895 # get the force constants from a vasprun.xml file vasprun = PhonopyVasprun(vasprun_path) force_constants, elements = vasprun.read_force_constants() force_constants *= force_constant_factor ph_unitcell = get_phonopy_structure(structure) ph = Phonopy(ph_unitcell, supercell_matrix) # set the force constants we found ph.set_force_constants(force_constants) # calculate the thermal properties ph.run_mesh(qpoint_mesh) ph.run_thermal_properties(t_min=t_min, t_max=t_max, t_step=t_step) # the thermal properties are for the unit cell tp_dict = ph.get_thermal_properties_dict() temperatures = tp_dict['temperatures'] # convert the units into our expected eV/atom-form (and per K) f_vib = tp_dict['free_energy'] * J_per_mol_to_eV_per_atom*1000 s_vib = tp_dict['entropy'] * J_per_mol_to_eV_per_atom cv_vib = tp_dict['heat_capacity'] * J_per_mol_to_eV_per_atom return temperatures, f_vib, s_vib, cv_vib, ph.force_constants, code_version
def _enable_phonopy(self): if self.phonopy is None: if self.structure is not None: self.phonopy = Phonopy( unitcell=self._phonopy_unit_cell, supercell_matrix=self._phonopy_supercell_matrix(), primitive_matrix=self.input["primitive_matrix"], factor=self.input["factor"], ) self.phonopy.generate_displacements( distance=self.input["displacement"]) self.to_hdf() else: raise ValueError( "No reference job/ No reference structure found.")
def build_phonon(self, atoms = None, supercell_matrix = None, primitive_matrix = None, distance = None): if atoms is None: atoms = self.atoms phonon = Phonopy(atoms, supercell_matrix, primitive_matrix = primitive_matrix) phonon.generate_displacements(distance = distance) self.log("[Phonopy] Atomic displacements:") disps = phonon.get_displacements() for d in disps: self.log("[Phonopy] %d %s" % (d[0], d[1:])) self.phonon = phonon
def _set_phonon(self): if self._supercell_matrix is None: cell = sort_cell_by_symbols( get_crystallographic_cell(self.get_cell())) self._supercell_matrix = estimate_supercell_matrix( cell, max_num_atoms=self._max_num_atoms) else: cell = self.get_cell() phonopy_cell = cell2atoms(cell) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix, dynamical_matrix_decimals=14, force_constants_decimals=14, symprec=self._symmetry_tolerance) self._phonon.generate_displacements( distance=self._distance, is_plusminus=self._displace_plusminus, is_diagonal=self._displace_diagonal) supercell = self._phonon.get_supercell() displacements = self._phonon.get_displacements() write_poscar(cell, filename="POSCAR-unitcell") write_poscar_yaml(cell, filename="POSCAR-unitcell.yaml") write_disp_yaml(displacements, supercell)
def phonopy_pre_process(cell, supercell_matrix=None): if supercell_matrix is None: smat = [[2,0,0], [0,2,0], [0,0,2]], else: smat = supercell_matrix phonon = Phonopy(cell, smat, primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) phonon.generate_displacements(distance=0.03) print("[Phonopy] Atomic displacements:") disps = phonon.get_displacements() for d in disps: print("[Phonopy] %d %s" % (d[0], d[1:])) return phonon
def test_properties(self): cell = read_vasp(os.path.join(data_dir, "..", "POSCAR_NaCl")) phonon = Phonopy(cell, np.diag([2, 2, 2]), primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) filename = os.path.join(data_dir, "..", "FORCE_SETS_NaCl") force_sets = parse_FORCE_SETS(filename=filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() dynmat = phonon.dynamical_matrix dynmat.set_dynamical_matrix([0, 0, 0]) self.assertTrue(id(dynmat.primitive) == id(dynmat.get_primitive())) self.assertTrue(id(dynmat.supercell) == id(dynmat.get_supercell())) np.testing.assert_allclose(dynmat.dynamical_matrix, dynmat.get_dynamical_matrix())
def get_phonopy_qha(energies, volumes, force_constants, structure, t_min, t_step, t_max, mesh, eos, pressure=0): """ Return phonopy QHA interface. Args: energies (list): volumes (list): force_constants (list): structure (Structure): t_min (float): min temperature t_step (float): temperature step t_max (float): max temperature mesh (list/tuple): reciprocal space density eos (str): equation of state used for fitting the energies and the volumes. options supported by phonopy: vinet, murnaghan, birch_murnaghan pressure (float): in GPa, optional. Returns: PhonopyQHA """ from phonopy import Phonopy from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import PhonopyQHA from phonopy.units import EVAngstromToGPa phon_atoms = PhonopyAtoms(symbols=[str(s.specie) for s in structure], scaled_positions=structure.frac_coords, cell=structure.lattice.matrix) scell = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] phonon = Phonopy(phon_atoms, scell) # compute the required phonon thermal properties temperatures = [] free_energy = [] entropy = [] cv = [] for f in force_constants: phonon.set_force_constants(-np.array(f)) phonon.set_mesh(list(mesh)) phonon.set_thermal_properties(t_step=t_step, t_min=t_min, t_max=t_max) t, g, e, c = phonon.get_thermal_properties() temperatures.append(t) free_energy.append(g) entropy.append(e) cv.append(c) # add pressure contribution energies = np.array(energies) + np.array(volumes) * pressure / EVAngstromToGPa # quasi-harmonic approx return PhonopyQHA(volumes, energies, eos=eos, temperatures=temperatures[0], free_energy=np.array(free_energy).T, cv=np.array(cv).T, entropy=np.array(entropy).T, t_max=np.max(temperatures[0]))
def _get_phonon_NaCl(self): cell = read_vasp(os.path.join(data_dir, "..", "POSCAR_NaCl")) phonon = Phonopy(cell, np.diag([2, 2, 2]), primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) filename = os.path.join(data_dir, "..", "FORCE_SETS_NaCl") force_sets = parse_FORCE_SETS(filename=filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() filename_born = os.path.join(data_dir, "..", "BORN_NaCl") nac_params = parse_BORN(phonon.get_primitive(), filename=filename_born) phonon.set_nac_params(nac_params) return phonon
def get_frequency(poscar_filename, force_sets_filename): bulk = read_vasp(poscar_filename) volume = bulk.get_volume() phonon = Phonopy(bulk, [[2, 0, 0], [0, 2, 0], [0, 0, 2]], is_auto_displacements=False) force_sets = parse_FORCE_SETS(filename=force_sets_filename) phonon.set_force_sets(force_sets) phonon.set_post_process([[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) return phonon.get_frequencies([0.5, 0.5, 0]), volume
def _get_phonon(self): cell = read_vasp(os.path.join(data_dir, "../POSCAR_NaCl")) phonon = Phonopy(cell, np.diag([2, 2, 2]), primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) filename = os.path.join(data_dir, "FORCE_SETS_NaCl") force_sets = parse_FORCE_SETS(filename=filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() supercell = phonon.get_supercell() born_elems = { "Na": [[1.08703, 0, 0], [0, 1.08703, 0], [0, 0, 1.08703]], "Cl": [[-1.08672, 0, 0], [0, -1.08672, 0], [0, 0, -1.08672]], } born = [born_elems[s] for s in ["Na", "Cl"]] epsilon = [[2.43533967, 0, 0], [0, 2.43533967, 0], [0, 0, 2.43533967]] factors = 14.400 phonon.set_nac_params({"born": born, "factor": factors, "dielectric": epsilon}) return phonon
def _set_phonon(self): cell = self.get_cell() phonopy_cell = cell2atoms(cell) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix, is_auto_displacements=False, dynamical_matrix_decimals=14, force_constants_decimals=14) self._phonon.generate_displacements( distance=self._distance, is_plusminus=self._displace_plusminus, is_diagonal=self._displace_diagonal) supercell = self._phonon.get_supercell() displacements = self._phonon.get_displacements() write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(displacements, supercell)
def _set_phonon(self): cell = self.get_cell() phonopy_cell = Atoms( cell=cell.get_lattice().T, scaled_positions=cell.get_points().T, symbols=cell.get_symbols()) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, is_auto_displacements=False) self._phonon.generate_displacements(distance=self._distance, is_diagonal=False) supercell = self._phonon.get_supercell() displacements = self._phonon.get_displacements() write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(displacements, supercell)
def _set_phonon_fc3(self): cell = self.get_cell() phonopy_cell = cell2atoms(cell) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix, dynamical_matrix_decimals=14, force_constants_decimals=14) self._phonon_fc3 = Phono3py(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix) self._phonon_fc3.generate_displacements(distance=self._distance, is_diagonal=self._is_diagonal) supercell = self._phonon_fc3.get_supercell() disp_dataset = self._phonon_fc3.get_displacement_dataset() self._phonon.set_displacement_dataset(disp_dataset) write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(self._phonon.get_displacements(), supercell, directions=self._phonon.get_displacement_directions()) write_disp_fc3_yaml(disp_dataset, supercell)
def _get_phonon(self, cell): phonon = Phonopy(cell, np.diag([1, 1, 1])) force_sets = parse_FORCE_SETS( filename=os.path.join(data_dir, "FORCE_SETS")) phonon.dataset = force_sets phonon.produce_force_constants() supercell = phonon.get_supercell() born_elems = {'Na': [[1.08703, 0, 0], [0, 1.08703, 0], [0, 0, 1.08703]], 'Cl': [[-1.08672, 0, 0], [0, -1.08672, 0], [0, 0, -1.08672]]} born = [born_elems[s] for s in supercell.get_chemical_symbols()] epsilon = [[2.43533967, 0, 0], [0, 2.43533967, 0], [0, 0, 2.43533967]] factors = 14.400 phonon.set_nac_params({'born': born, 'factor': factors, 'dielectric': epsilon}) return phonon
import phonopy.interface.vasp as vasp import numpy as np import lxml.etree as etree from phonopy import Phonopy from phonopy.structure.atoms import Atoms as PhonopyAtoms vasprun = etree.iterparse('vasprun.xml', tag='varray') fc = vasp.get_force_constants_vasprun_xml(vasprun) primitive = vasp.get_atoms_from_poscar(open('POSCAR-p'),'W') superc = vasp.get_atoms_from_poscar(open('POSCAR'),'W') print superc.get_scaled_positions() a = 5.404 bulk = PhonopyAtoms(symbols=['W'] * 216, positions=superc.get_scaled_positions()) bulk.set_cell(np.diag((a, a, a))) phonon = Phonopy(bulk,[[1,0,0],[0,1,0],[0,0,1]],primitive_matrix=[[-0.5, 0.5, 0.5],[0.5, -0.5, 0.5],[0.5, 0.5, -0.5]]) phonon.set_force_constants(fc) mesh = [3, 3, 3] phonon.set_mesh(mesh) qpoints, weights, frequencies, eigvecs = phonon.get_mesh() phonon.set_total_DOS() phonon.plot_total_DOS().show()
(0, 0.5, 0.5), (0.5, 0, 0.5), (0.5, 0.5, 0), (0.25, 0.25, 0.25), (0.25, 0.75, 0.75), (0.75, 0.25, 0.75), (0.75, 0.75, 0.25)] ) bulk.set_cell(np.diag((a, a, a))) calc = GPAW(mode=PW(300), kpts={'size': (4, 4, 4)}, symmetry={'symmorphic': False}) phonon = Phonopy(bulk, [[1,0,0],[0,1,0],[0,0,1]], primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], distance=0.01) print "[Phonopy] Atomic displacements:" disps = phonon.get_displacements() for d in disps: print "[Phonopy]", d[0], d[1:] supercells = phonon.get_supercells_with_displacements() # Force calculations by calculator set_of_forces = [] for scell in supercells: cell = Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True)
from phonopy import Phonopy from phonopy.interface.vasp import read_vasp from phonopy.file_IO import parse_FORCE_SETS from phonopy.file_IO import parse_FORCE_CONSTANTS, write_FORCE_CONSTANTS cell = read_vasp("POSCAR") phonon = Phonopy(cell, [[2, 0, 0], [0, 2, 0], [0, 0, 2]]) force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS") force_constants = parse_FORCE_CONSTANTS() phonon.set_force_constants(force_constants) phonon.symmetrize_force_constants(iteration=1) write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS_NEW")
class PhononBase(TaskElement): """PhononBase class This is an interface to phonopy. """ def __init__(self, directory=None, name=None, supercell_matrix=None, primitive_matrix=None, distance=None, lattice_tolerance=None, force_tolerance=None, pressure_target=None, stress_tolerance=None, max_increase=None, max_iteration=None, min_iteration=None, traverse=False, is_cell_relaxed=False): TaskElement.__init__(self) self._directory = directory if not name: self._name = directory else: self._name = name self._task_type = "phonon" self._supercell_matrix = supercell_matrix self._primitive_matrix = primitive_matrix self._distance = distance self._lattice_tolerance = lattice_tolerance self._pressure_target = pressure_target self._stress_tolerance = stress_tolerance self._force_tolerance = force_tolerance self._max_increase = max_increase self._max_iteration = max_iteration self._min_iteration = min_iteration self._traverse = traverse self._is_cell_relaxed = is_cell_relaxed self._stage = 0 self._tasks = [] self._energy = None self._cell = None self._phonon = None # Phonopy object def get_phonon(self): return self._phonon def get_cell(self): if self._is_cell_relaxed: return self._cell else: return self._phonon_tasks[0].get_cell() def get_energy(self): """Return energies at geometry optimization steps""" return self._energy def set_status(self): done = True terminate = False for task in self._tasks: done &= task.done() if task.get_status() == "terminate": terminate = True if done: if terminate: self._status = "terminate" else: self._status = "next" self._write_yaml() def begin(self): if not self._job: print "set_job has to be executed." raise self._overwrite_settings() if self._is_cell_relaxed: self._phonon_tasks = [None] self._set_stage1() else: self._set_stage0() def end(self): pass def done(self): return ("terminate" in self._status or "done" in self._status or "next" in self._status) def next(self): if self._stage == 0: if "next" in self._status: self._energy = self._tasks[0].get_energy() self._comment = "%s\\n%f" % ( self._tasks[0].get_space_group()['international_standard'], self._energy) self._set_stage1() return self._tasks elif "terminate" in self._status and self._traverse == "restart": self._traverse = False self._set_stage0() return self._tasks else: raise StopIteration else: # task 1..n: displaced supercells if "next" in self._status: self._status = "done" forces = [] for task in self._phonon_tasks[1:]: forces.append(task.get_properties()['forces'][-1]) self._write_FORCE_SETS(forces) self._phonon.set_post_process(self._primitive_matrix, forces, force_constants_decimals=14) self._tasks = [] raise StopIteration elif "terminate" in self._status and self._traverse == "restart": self._traverse = False disp_terminated = [] for i, task in enumerate(self._tasks): if task.get_status() == "terminate": disp_terminated.append(i) tasks = self._get_displacement_tasks()[1:] self._tasks = [] for i in disp_terminated: self._tasks.append(tasks[i]) self._phonon_tasks[i + 1] = tasks[i] self._status = "displacements" return self._tasks else: raise StopIteration def _set_stage0(self): self._status = "equilibrium" task = self._get_equilibrium_task() self._phonon_tasks = [task] self._tasks = [task] def _set_stage1(self): self._stage = 1 self._status = "displacements" self._set_phonon() self._tasks = self._get_displacement_tasks()[1:] self._phonon_tasks += self._tasks def _set_phonon(self): cell = self.get_cell() phonopy_cell = Atoms( cell=cell.get_lattice().T, scaled_positions=cell.get_points().T, symbols=cell.get_symbols()) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, is_auto_displacements=False) self._phonon.generate_displacements(distance=self._distance, is_diagonal=False) supercell = self._phonon.get_supercell() displacements = self._phonon.get_displacements() write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(displacements, supercell) def _write_FORCE_SETS(self, forces): displacements = [[x[0], x[1:4]] for x in self._phonon.get_displacements()] natom = self._phonon.get_supercell().get_number_of_atoms() write_FORCE_SETS("FORCE_SETS", natom, displacements, forces, verbose=False) def _write_yaml(self): w = open("%s.yaml" % self._directory, 'w') if self._phonon_tasks[0]: if self._lattice_tolerance is not None: w.write("lattice_tolerance: %f\n" % self._lattice_tolerance) if self._stress_tolerance is not None: w.write("stress_tolerance: %f\n" % self._stress_tolerance) w.write("pressure_target: %f\n" % self._pressure_target) w.write("force_tolerance: %f\n" % self._force_tolerance) w.write("max_increase: %f\n" % self._max_increase) w.write("max_iteration: %d\n" % self._max_iteration) w.write("min_iteration: %d\n" % self._min_iteration) w.write("supercell_matrix:\n") for row in self._supercell_matrix: w.write("- [ %3d, %3d, %3d ]\n" % tuple(row)) w.write("primitive_matrix:\n") for row in self._primitive_matrix: w.write("- [ %6.3f, %6.3f, %6.3f ]\n" % tuple(row)) w.write("distance: %f\n" % self._distance) w.write("iteration: %d\n" % self._phonon_tasks[0].get_stage()) if self._energy: w.write("electric_total_energy: %20.10f\n" % self._energy) w.write("status: %s\n" % self._status) w.write("tasks:\n") for task in self._phonon_tasks: if task and task.get_status(): w.write("- name: %s\n" % task.get_name()) w.write(" status: %s\n" % task.get_status()) w.close()
# This can be given via a PhonopyAtoms class as follows: # unitcell = PhonopyAtoms(symbols=(['Na'] * 4 + ['Cl'] * 4), # cell=(np.eye(3) * 5.6903014761756712), # scaled_positions=[[0, 0, 0], # [0, 0.5, 0.5], # [0.5, 0, 0.5], # [0.5, 0.5, 0], # [0.5, 0.5, 0.5], # [0.5, 0, 0], # [0, 0.5, 0], # [0, 0, 0.5]]) phonon = Phonopy(unitcell, [[2, 0, 0], [0, 2, 0], [0, 0, 2]], primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) symmetry = phonon.get_symmetry() print "Space group:", symmetry.get_international_table() force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() primitive = phonon.get_primitive() # Born effective charges and dielectric constants are read from BORN file. nac_params = parse_BORN(primitive, filename="BORN") # Or it can be of course given by hand as follows:
from phonopy import Phonopy from phonopy.interface.vasp import read_vasp from phonopy.file_IO import parse_FORCE_SETS, parse_BORN import numpy as np cell = read_vasp("POSCAR") # Initialize phonon. Supercell matrix has to have the shape of (3, 3) phonon = Phonopy(cell, np.diag([3, 3, 2])) symmetry = phonon.get_symmetry() print "Space group:", symmetry.get_international_table() force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() # Character table phonon.set_irreps([1./3, 1./3, 0], 1e-4) ct = phonon.get_irreps() band_indices = ct.get_band_indices() characters = np.rint(ct.get_characters()).real for bi, cts in zip(band_indices, characters): print np.array(bi) + 1, cts # phonon.show_character_table()
calc = GPAW(gpts=(n, n, n), nbands=8*3, width=0.01, kpts=(2, 2, 2), convergence={'eigenstates': 1e-9} ) # Phonopy pre-process print "------" print "Phonon" print "------" # 1st arg. is the input unit cell. # 2nd arg. is the supercell lattice relative to the unit cell. # 'distance' is the distance of displacements. # Default symmetry tolerance is 1e-5 in fractional coordinates. phonon = Phonopy(bulk, [[1,0,0],[0,1,0],[0,0,1]], distance=0.01) phonon.print_displacements() supercells = phonon.get_supercells_with_displacements() # Force calculations by calculator set_of_forces = [] for scell in supercells: cell = Atoms( symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True ) cell.set_calculator(calc) forces = cell.get_forces() drift_force = forces.sum(axis=0) print " ---------------------------------" print " ", "%11.5f"*3 % tuple(drift_force)
from phonopy import Phonopy from phonopy.interface.vasp import read_vasp from phonopy.file_IO import parse_FORCE_SETS, parse_BORN import numpy as np cell = read_vasp("POSCAR") # Initialize phonon. Supercell matrix has to have the shape of (3, 3) phonon = Phonopy(cell, np.diag([2, 2, 1])) symmetry = phonon.get_symmetry() print "Space group:", symmetry.get_international_table() # Read and convert forces and displacements force_sets = parse_FORCE_SETS(cell.get_number_of_atoms() * 4) # Sets of forces have to be set before phonon.set_post_process or # at phonon.set_post_process(..., sets_of_forces=sets_of_forces, ...). phonon.set_force_sets(force_sets) # To activate non-analytical term correction. phonon.set_post_process(primitive_matrix=[[2./3, -1./3, -1./3], [1./3, 1./3, -2./3], [1./3, 1./3, 1./3]]) # Parameters for non-analytical term correction can be set # also after phonon.set_post_process born = parse_BORN(phonon.get_primitive()) phonon.set_nac_params(born) # Example to obtain dynamical matrix dmat = phonon.get_dynamical_matrix_at_q([0,0,0])
#!/usr/bin/env python from cogue.task.phonon_relax import get_unstable_modulations from phonopy import Phonopy from phonopy.interface.vasp import read_vasp from phonopy.file_IO import parse_FORCE_SETS, parse_BORN import numpy as np cutoff_eigenvalue = -0.02 supercell_dimension = [2, 2, 2] cell = read_vasp("POSCAR-unitcell") phonon = Phonopy(cell, np.diag(supercell_dimension)) force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() phonon.set_mesh(supercell_dimension, is_gamma_center=True) get_unstable_modulations( phonon, supercell_dimension, cutoff_eigenvalue=cutoff_eigenvalue, symmetry_tolerance=0.1, max_displacement=0.11 )
from phonopy import Phonopy from phonopy.interface.vasp import read_vasp from phonopy.file_IO import parse_FORCE_SETS, parse_BORN import numpy as np cell = read_vasp("POSCAR") # Initialize phonon. Supercell matrix has to have the shape of (3, 3) phonon = Phonopy(cell, np.diag([2, 2, 1]), primitive_matrix=[[2./3, -1./3, -1./3], [1./3, 1./3, -2./3], [1./3, 1./3, 1./3]]) symmetry = phonon.get_symmetry() print "Space group:", symmetry.get_international_table() force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() born = parse_BORN(phonon.get_primitive()) phonon.set_nac_params(born) # Example to obtain dynamical matrix dmat = phonon.get_dynamical_matrix_at_q([0,0,0]) print dmat # Example of band structure calculation bands = [] q_start = np.array([1./3, 1./3, 0])
from phonopy.interface.vasp import read_vasp from phonopy.file_IO import parse_FORCE_SETS, parse_BORN import numpy as np def append_band(bands, q_start, q_end): band = [] for i in range(51): band.append(np.array(q_start) + (np.array(q_end) - np.array(q_start)) / 50 * i) bands.append(band) bulk = read_vasp("POSCAR") phonon = Phonopy(bulk, [[2, 0, 0], [0, 2, 0], [0, 0, 2]], primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], is_auto_displacements=False) symmetry = phonon.get_symmetry() print "Space group:", symmetry.get_international_table() force_sets = parse_FORCE_SETS() phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() born = [[[1.08703, 0, 0], [0, 1.08703, 0], [0, 0, 1.08703]], [[-1.08672, 0, 0],
class PhononBase(TaskElement): """PhononBase class This is an interface to phonopy. """ def __init__(self, directory=None, name=None, supercell_matrix=None, primitive_matrix=None, distance=None, displace_plusminus='auto', displace_diagonal=False, lattice_tolerance=None, force_tolerance=None, pressure_target=None, stress_tolerance=None, max_increase=None, max_iteration=None, min_iteration=None, is_cell_relaxed=False, stop_condition=None, traverse=False): TaskElement.__init__(self) self._directory = directory if not name: self._name = directory else: self._name = name self._task_type = "phonon" self._supercell_matrix = supercell_matrix self._primitive_matrix = primitive_matrix self._distance = distance self._displace_plusminus = displace_plusminus self._displace_diagonal = displace_diagonal self._lattice_tolerance = lattice_tolerance self._pressure_target = pressure_target self._stress_tolerance = stress_tolerance self._force_tolerance = force_tolerance self._max_increase = max_increase self._max_iteration = max_iteration self._min_iteration = min_iteration self._is_cell_relaxed = is_cell_relaxed self._stop_condition = stop_condition self._traverse = traverse self._stage = 0 self._tasks = [] self._energy = None self._space_group = None self._cell = None self._phonon = None # Phonopy object self._phonon_tasks = None # Phonopy object def get_phonon(self): return self._phonon def get_cell(self): if self._is_cell_relaxed: return self._cell else: return self._phonon_tasks[0].get_cell() def get_energy(self): """Return energies at geometry optimization steps""" return self._energy def get_space_group(self): return self._space_group def set_status(self): if self._stage == 0: task = self._tasks[0] if task.done(): self._space_group = task.get_space_group() status = task.get_status() if status == "done": if not self._evaluate_stop_condition(): self._status = "next" else: self._status = status else: done = True terminate = True for task in self._tasks: done &= task.done() terminate &= (task.get_status() == "terminate") if done: if terminate: self._status = "terminate" else: self._status = "next" self._write_yaml() def begin(self): if not self._job: print "set_job has to be executed." raise self._overwrite_settings() if self._is_cell_relaxed: self._phonon_tasks = [None] self._set_stage1() else: self._set_stage0() def done(self): return (self._status == "terminate" or self._status == "done" or self._status == "max_iteration" or self._status == "low_symmetry" or self._status == "next") def next(self): if self._stage == 0: if self._status == "next": self._energy = self._tasks[0].get_energy() num_atom = len(self._tasks[0].get_cell().get_symbols()) self._comment = self._space_group['international_standard'] self._comment += "\\n%f/%d" % (self._energy, num_atom) self._set_stage1() return self._tasks elif (self._status == "terminate" and self._traverse == "restart"): self._traverse = False self._set_stage0() return self._tasks else: # task 1..n: displaced supercells if self._status == "next": self._status = "done" forces = [] for task in self._tasks: forces.append(task.get_properties()['forces'][-1]) self._phonon.produce_force_constants(forces) write_FORCE_SETS(self._phonon.get_displacement_dataset()) self._tasks = [] elif self._status == "terminate" and self._traverse == "restart": self._traverse = False disp_terminated = [] for i, task in enumerate(self._tasks): if task.get_status() == "terminate": disp_terminated.append(i) tasks = self._get_displacement_tasks() self._tasks = [] for i in disp_terminated: self._tasks.append(tasks[i]) self._phonon_tasks[i + 1] = tasks[i] self._status = "displacements" return self._tasks self._write_yaml() raise StopIteration def _set_stage0(self): self._status = "equilibrium" task = self._get_equilibrium_task() self._phonon_tasks = [task] self._tasks = [task] def _set_stage1(self): self._stage = 1 self._status = "displacements" self._set_phonon() self._tasks = self._get_displacement_tasks() self._phonon_tasks += self._tasks def _evaluate_stop_condition(self): if self._stop_condition: if "symmetry_operations" in self._stop_condition: num_ops = len(self._space_group['rotations']) if (num_ops < self._stop_condition['symmetry_operations']): self._status = "low_symmetry" return True return False def _set_phonon(self): cell = self.get_cell() phonopy_cell = cell2atoms(cell) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix, is_auto_displacements=False, dynamical_matrix_decimals=14, force_constants_decimals=14) self._phonon.generate_displacements( distance=self._distance, is_plusminus=self._displace_plusminus, is_diagonal=self._displace_diagonal) supercell = self._phonon.get_supercell() displacements = self._phonon.get_displacements() write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(displacements, supercell) def _write_yaml(self): w = open("%s.yaml" % self._directory, 'w') w.write("supercell_matrix:\n") for row in self._supercell_matrix: w.write("- [ %3d, %3d, %3d ]\n" % tuple(row)) w.write("primitive_matrix:\n") for row in self._primitive_matrix: w.write("- [ %6.3f, %6.3f, %6.3f ]\n" % tuple(row)) w.write("distance: %f\n" % self._distance) if self._phonon_tasks[0]: if self._lattice_tolerance is not None: w.write("lattice_tolerance: %f\n" % self._lattice_tolerance) if self._stress_tolerance is not None: w.write("stress_tolerance: %f\n" % self._stress_tolerance) w.write("pressure_target: %f\n" % self._pressure_target) w.write("force_tolerance: %f\n" % self._force_tolerance) if self._max_increase is None: w.write("max_increase: unset\n") else: w.write("max_increase: %f\n" % self._max_increase) w.write("max_iteration: %d\n" % self._max_iteration) w.write("min_iteration: %d\n" % self._min_iteration) w.write("iteration: %d\n" % self._phonon_tasks[0].get_stage()) if self._energy: w.write("electric_total_energy: %20.10f\n" % self._energy) w.write("status: %s\n" % self._status) w.write("tasks:\n") for task in self._phonon_tasks: if task and task.get_status(): w.write("- name: %s\n" % task.get_name()) w.write(" status: %s\n" % task.get_status()) w.close()
from phonopy.file_IO import parse_FORCE_SETS def append_band(bands, q_start, q_end): band = [] for i in range(51): band.append(np.array(q_start) + (np.array(q_end) - np.array(q_start)) / 50 * i) bands.append(band) phonons = {} for vol in ("orig", "plus", "minus"): unitcell = read_vasp("%s/POSCAR-unitcell" % vol) phonon = Phonopy(unitcell, [[2, 0, 0], [0, 2, 0], [0, 0, 2]], primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]]) force_sets = parse_FORCE_SETS(filename="%s/FORCE_SETS" % vol) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() phonons[vol] = phonon gruneisen = PhonopyGruneisen(phonons["orig"], phonons["plus"], phonons["minus"]) gruneisen.set_mesh([2, 2, 2]) q_points, _, frequencies, _, gammas = gruneisen.get_mesh() for q, freq, g in zip(q_points, frequencies, gammas):
class PhononFC3Base(TaskElement): """PhononFC3Base class This is an interface to anharmonic phonopy. """ def __init__(self, directory=None, name=None, supercell_matrix=None, primitive_matrix=None, distance=None, is_diagonal=True, check_imaginary=True, cutoff_frequency=None, lattice_tolerance=None, force_tolerance=None, pressure_target=None, stress_tolerance=None, max_increase=None, max_iteration=None, min_iteration=None, is_cell_relaxed=False, traverse=False): TaskElement.__init__(self) self._directory = directory if not name: self._name = directory else: self._name = name self._task_type = "anharmonic_phonon" self._supercell_matrix = supercell_matrix self._primitive_matrix = primitive_matrix self._distance = distance self._is_diagonal = is_diagonal self._check_imaginary = check_imaginary self._cutoff_frequency = cutoff_frequency # determine imaginary freq. self._lattice_tolerance = lattice_tolerance self._pressure_target = pressure_target self._stress_tolerance = stress_tolerance self._force_tolerance = force_tolerance self._max_increase = max_increase self._max_iteration = max_iteration self._min_iteration = min_iteration self._traverse = traverse self._is_cell_relaxed = is_cell_relaxed self._stage = 0 self._tasks = [] self._energy = None self._cell = None self._phonon = None # Phonopy object self._phonon_fc3 = None # Phono3py object self._phonon_fc3_tasks = None def get_phonon(self): return self._phonon def get_phonon_fc3(self): for i, task in enumerate(self._phonon_fc3_tasks[1:]): forces_fc3.append(task.get_properties()['forces'][-1]) disp_dataset = self._phonon_fc3.get_displacement_dataset() self._phonon_fc3.produce_fc3(forces_fc3) return self._phonon_fc3 def get_cell(self): if self._is_cell_relaxed: return self._cell else: return self._phonon_fc3_tasks[0].get_cell() def get_energy(self): """Return energies at geometry optimization steps""" return self._energy def set_status(self): if self._stage == 0: task = self._tasks[0] if task.done(): status = task.get_status() if status == "done": self._status = "next" else: self._status = status else: done = True terminate = False for i, task in enumerate(self._tasks): done &= task.done() terminate |= (task.get_status() == "terminate") if done: if terminate: self._status = "terminate" else: self._status = "next" self._write_yaml() def begin(self): if not self._job: print("set_job has to be executed.") raise RuntimeError if self._is_cell_relaxed: self._phonon_fc3_tasks = [None] self._set_stage1() else: self._set_stage0() def end(self): pass def done(self): return (self._status == "terminate" or self._status == "done" or self._status == "max_iteration" or self._status == "next" or self._status == "imaginary_mode") def __next__(self): return self.next() def next(self): if self._stage == 0: if "next" in self._status: self._energy = self._tasks[0].get_energy() self._comment = "%s\\n%f" % ( self._tasks[0].get_space_group()['international'], self._energy) self._set_stage1() return self._tasks elif "terminate" in self._status and self._traverse == "restart": self._traverse = False self._set_stage0() return self._tasks else: raise StopIteration elif self._stage == 1: if "next" in self._status: disp_dataset = self._phonon_fc3.get_displacement_dataset() for disp1, task in zip(disp_dataset['first_atoms'], self._tasks): disp1['forces'] = task.get_properties()['forces'][-1] write_FORCE_SETS(disp_dataset) self._phonon.set_displacement_dataset(disp_dataset) self._phonon.produce_force_constants( calculate_full_force_constants=False) if self._exist_imaginary_mode(): self._status = "imaginary_mode" self._write_yaml() self._tasks = [] raise StopIteration else: self._set_stage2() return self._tasks elif "terminate" in self._status and self._traverse == "restart": self._reset_stage1() return self._tasks else: raise StopIteration elif self._stage == 2: if "next" in self._status: self._status = "done" forces_fc3 = [] for i, task in enumerate(self._phonon_fc3_tasks[1:]): forces_fc3.append(task.get_properties()['forces'][-1]) disp_dataset = self._phonon_fc3.get_displacement_dataset() write_FORCES_FC3(disp_dataset, forces_fc3) self._tasks = [] raise StopIteration elif "terminate" in self._status and self._traverse == "restart": self._reset_stage2() return self._tasks else: raise StopIteration else: # stage2 pass def _set_stage0(self): self._status = "equilibrium" task = self._get_equilibrium_task() self._phonon_fc3_tasks = [task] self._tasks = [task] def _set_stage1(self): self._set_phonon_fc3() if self._check_imaginary: self._stage = 1 self._status = "fc2_displacements" disp_dataset = self._phonon_fc3.get_displacement_dataset() self._tasks = self._get_displacement_tasks( stop=len(disp_dataset['first_atoms'])) self._phonon_fc3_tasks += self._tasks else: self._set_stage2() def _reset_stage1(self): self._traverse = False disp_terminated = [] for i, task in enumerate(self._tasks): if task.get_status() == "terminate": disp_terminated.append(i) disp_dataset = self._phonon_fc3.get_displacement_dataset() tasks = self._get_displacement_tasks( stop=len(disp_dataset['first_atoms'])) self._tasks = [] for i in disp_terminated: self._tasks.append(tasks[i]) self._phonon_fc3_tasks[i + 1] = tasks[i] self._status = "fc2_displacements" def _set_stage2(self): self._stage = 2 self._status = "fc3_displacements" if self._check_imaginary: disp_dataset = self._phonon_fc3.get_displacement_dataset() start_index = len(disp_dataset['first_atoms']) else: start_index = 0 self._tasks = self._get_displacement_tasks(start=start_index) self._phonon_fc3_tasks += self._tasks def _reset_stage2(self): self._traverse = False disp_terminated = [] for i, task in enumerate(self._tasks): if task.get_status() == "terminate": disp_terminated.append(i) if self._check_imaginary: disp_dataset = self._phonon_fc3.get_displacement_dataset() start_index = len(disp_dataset['first_atoms']) else: start_index = 0 tasks = self._get_displacement_tasks(start=start_index) self._tasks = [] for i in disp_terminated: self._tasks.append(tasks[i]) self._phonon_fc3_tasks[i + 1 + start_index] = tasks[i] self._status = "fc3_displacements" def _set_phonon_fc3(self): cell = self.get_cell() phonopy_cell = cell2atoms(cell) self._phonon = Phonopy(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix, dynamical_matrix_decimals=14, force_constants_decimals=14) self._phonon_fc3 = Phono3py(phonopy_cell, self._supercell_matrix, primitive_matrix=self._primitive_matrix) self._phonon_fc3.generate_displacements(distance=self._distance, is_diagonal=self._is_diagonal) supercell = self._phonon_fc3.get_supercell() disp_dataset = self._phonon_fc3.get_displacement_dataset() self._phonon.set_displacement_dataset(disp_dataset) write_poscar(cell, "POSCAR-unitcell") write_disp_yaml(self._phonon.get_displacements(), supercell, directions=self._phonon.get_displacement_directions()) write_disp_fc3_yaml(disp_dataset, supercell) def _exist_imaginary_mode(self): if self._primitive_matrix is None: pmat = np.eye(3) else: pmat = self._primitive_matrix exact_point_matrix = np.dot(np.linalg.inv(self._supercell_matrix), pmat).T max_integer = np.rint(np.amax(np.abs(np.linalg.inv(exact_point_matrix)))) q_points = [] for i in np.arange(-max_integer, max_integer + 1): for j in np.arange(-max_integer, max_integer + 1): for k in np.arange(-max_integer, max_integer + 1): q = np.dot(exact_point_matrix, [i, j, k]) if (-1 < q).all() and (q < 1).all(): q_points.append(q) self._phonon.set_qpoints_phonon(q_points) frequencies = self._phonon.get_qpoints_phonon()[0] if (frequencies < self._cutoff_frequency).any(): self._log = "Stop at phonon calculation due to imaginary modes" return True else: return False def _write_yaml(self): w = open("%s.yaml" % self._directory, 'w') if self._lattice_tolerance is not None: w.write("lattice_tolerance: %f\n" % self._lattice_tolerance) if self._stress_tolerance is not None: w.write("stress_tolerance: %f\n" % self._stress_tolerance) w.write("pressure_target: %f\n" % self._pressure_target) w.write("force_tolerance: %f\n" % self._force_tolerance) if self._max_increase is None: w.write("max_increase: unset\n") else: w.write("max_increase: %f\n" % self._max_increase) w.write("max_iteration: %d\n" % self._max_iteration) w.write("min_iteration: %d\n" % self._min_iteration) w.write("supercell_matrix:\n") for row in self._supercell_matrix: w.write("- [ %3d, %3d, %3d ]\n" % tuple(row)) if self._primitive_matrix is not None: w.write("primitive_matrix:\n") for row in self._primitive_matrix: w.write("- [ %6.3f, %6.3f, %6.3f ]\n" % tuple(row)) w.write("distance: %f\n" % self._distance) if self._phonon_fc3_tasks[0] is not None: w.write("iteration: %d\n" % self._phonon_fc3_tasks[0].get_stage()) if self._energy: w.write("electric_total_energy: %20.10f\n" % self._energy) w.write("status: %s\n" % self._status) w.write("tasks:\n") for task in self._phonon_fc3_tasks: if task and task.get_status(): w.write("- name: %s\n" % task.get_name()) w.write(" status: %s\n" % task.get_status()) w.close()