def _get_phonon(self, spgtype, dim, pmat): cell = read_vasp("POSCAR_%s" % spgtype) phonon = Phonopy(cell, np.diag(dim), primitive_matrix=pmat) force_sets = parse_FORCE_SETS(filename="FORCE_SETS_%s" % spgtype) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() 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): phonon = Phonopy(cell, np.diag([1, 1, 1])) force_sets = parse_FORCE_SETS( filename=os.path.join(data_dir, "FORCE_SETS")) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() return phonon
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 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 do_phonons(strt=None, parameters=None, c_size=25): """ Setting up phonopy job using LAMMPS Args: strt: Structure object parameters: LAMMPS input file parameters c_size: cell-size """ p = get_phonopy_atoms(mat=strt) bulk = p dim1 = int((float(c_size) / float(max(abs(strt.lattice.matrix[0]))))) + 1 dim2 = int(float(c_size) / float(max(abs(strt.lattice.matrix[1])))) + 1 dim3 = int(float(c_size) / float(max(abs(strt.lattice.matrix[2])))) + 1 Poscar(strt).write_file("POSCAR") tmp = strt.copy() tmp.make_supercell([dim1, dim2, dim3]) Poscar(tmp).write_file("POSCAR-Super.vasp") phonon = Phonopy(bulk, [[dim1, 0, 0], [0, dim2, 0], [0, 0, dim3]]) # , 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 = [] disp = 0 for scell in supercells: cell = Atoms( symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True, ) disp = disp + 1 mat = Poscar(AseAtomsAdaptor().get_structure(cell)) mat.comment = str("disp-") + str(disp) parameters["min"] = "skip" parameters["control_file"] = "/users/knc6/in.phonon" # a,b,forces=run_job(mat=mat,parameters={'min':'skip','pair_coeff': '/data/knc6/JARVIS-FF-NEW/ALLOY4/Mishin-Ni-Al-2009.eam.alloy', 'control_file': '/users/knc6/in.phonon', 'pair_style': 'eam/alloy', 'atom_style': 'charge'}) a, b, forces = run_job(mat=mat, parameters=parameters) print("forces=", forces) drift_force = forces.sum(axis=0) print("drift forces=", drift_force) print("[Phonopy] Drift force:", "%11.5f" * 3 % tuple(drift_force)) # Simple translational invariance for force in forces: force -= drift_force / forces.shape[0] set_of_forces.append(forces) phonon.produce_force_constants(forces=set_of_forces) write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS") print() print("[Phonopy] Phonon frequencies at Gamma:")
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 _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_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 phonons(model, bulk, supercell, dx, mesh=None, points=None, n_points=50): import model unitcell = PhonopyAtoms(symbols=bulk.get_chemical_symbols(), cell=bulk.get_cell(), scaled_positions=bulk.get_scaled_positions()) phonon = Phonopy(unitcell, supercell) phonon.generate_displacements(distance=dx) sets_of_forces = [] for s in phonon.get_supercells_with_displacements(): at = Atoms(cell=s.get_cell(), symbols=s.get_chemical_symbols(), scaled_positions=s.get_scaled_positions(), pbc=3 * [True]) at.set_calculator(model.calculator) sets_of_forces.append(at.get_forces()) phonon.set_forces(sets_of_forces=sets_of_forces) phonon.produce_force_constants() properties = {} if mesh is not None: phonon.set_mesh(mesh, is_gamma_center=True) qpoints, weights, frequencies, eigvecs = phonon.get_mesh() properties["frequencies"] = frequencies.tolist() properties["weights"] = weights.tolist() if points is not None: bands = [] for i in range(len(points) - 1): band = [] for r in np.linspace(0, 1, n_points): band.append(points[i] + (points[i + 1] - points[i]) * r) bands.append(band) phonon.set_band_structure(bands, is_eigenvectors=True, is_band_connection=False) band_q_points, band_distances, band_frequencies, band_eigvecs = phonon.get_band_structure( ) band_distance_max = np.max(band_distances) band_distances = [(_b / band_distance_max).tolist() for _b in band_distances] band_frequencies = [_b.tolist() for _b in band_frequencies] properties["band_q_points"] = band_q_points properties["band_distances"] = band_distances properties["band_frequencies"] = band_frequencies properties["band_eigvecs"] = band_eigvecs properties["phonopy"] = phonon return properties
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 _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) filename = os.path.join(data_dir, "FORCE_SETS_%s" % spgtype) force_sets = parse_FORCE_SETS(filename=filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() print(phonon.get_symmetry().get_pointgroup()) return 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 get_frequency(poscar_filename, force_sets_filename): unitcell = read_vasp(poscar_filename) volume = unitcell.get_volume() 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=force_sets_filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() return phonon.get_frequencies([0.5, 0.5, 0]), volume
def do_phonons(strt=None,parameters=None): p= get_phonopy_atoms(mat=strt) bulk =p c_size=parameters['phon_size'] dim1=int((float(c_size)/float( max(abs(strt.lattice.matrix[0])))))+1 dim2=int(float(c_size)/float( max(abs(strt.lattice.matrix[1]))))+1 dim3=int(float(c_size)/float( max(abs(strt.lattice.matrix[2]))))+1 Poscar(strt).write_file("POSCAR") tmp=strt.copy() tmp.make_supercell([dim1,dim2,dim3]) Poscar(tmp).write_file("POSCAR-Super.vasp") print ('supercells',dim1,dim2,dim3) phonon = Phonopy(bulk,[[dim1,0,0],[0,dim2,0],[0,0,dim3]]) 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 = [] disp=0 for scell in supercells: cell = Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True) disp=disp+1 mat = Poscar(AseAtomsAdaptor().get_structure(cell)) mat.comment=str("disp-")+str(disp) parameters['min']='skip' parameters['control_file']= parameters['phonon_control_file'] #'/users/knc6/in.phonon' #a,b,forces=run_job(mat=mat,parameters={'min':'skip','pair_coeff': '/data/knc6/JARVIS-FF-NEW/ALLOY4/Mishin-Ni-Al-2009.eam.alloy', 'control_file': '/users/knc6/in.phonon', 'pair_style': 'eam/alloy', 'atom_style': 'charge'}) a,b,forces=run_job(mat=mat,parameters=parameters) #print "forces=",forces drift_force = forces.sum(axis=0) #print "drift forces=",drift_force #print "[Phonopy] Drift force:", "%11.5f"*3 % tuple(drift_force) # Simple translational invariance for force in forces: force -= drift_force / forces.shape[0] set_of_forces.append(forces) phonon.produce_force_constants(forces=set_of_forces) write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS") #print #print "[Phonopy] Phonon frequencies at Gamma:" for i, freq in enumerate(phonon.get_frequencies((0, 0, 0))): print ("[Phonopy] %3d: %10.5f THz" % (i + 1, freq)) # THz
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() 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 _calc_quick(atoms, supercell=(1, 1, 1), delta=0.01): """Calculates the Hessian for a given atoms object just like :func:`calc`, *but*, it uses symmetry to speed up the calculation. Depending on the calculator being used, it is possible that the symmetrized result may be different from the full result with all displacements, done manually by :func:`calc`. Args: atoms (matdb.atoms.Atoms): atomic structure of the *primitive*. supercell (list): or `tuple` or :class:`numpy.ndarray` specifying the integer supercell matrix. delta (float): displacement in Angstroms of each atom when computing the phonons. Returns: numpy.ndarray: Hessian matrix that has dimension `(natoms*3, natoms*3)`, where `natoms` is the number of atoms in the *supercell*. """ #We need to make sure we are at the zero of the potential before ratoms = atoms.copy() try: with open("phonons.log", 'w') as f: with redirect_stdout(f): print(ratoms.get_forces()) minim = FIRE(ratoms) minim.run(fmax=1e-4, steps=100) except: #The potential is unstable probably. Issue a warning. msg.warn( "Couldn't optimize the atoms object. Potential may be unstable.") primitive = matdb_to_phonopy(ratoms) phonon = Phonopy(primitive, conform_supercell(supercell)) phonon.generate_displacements(distance=delta) supercells = phonon.get_supercells_with_displacements() pot = atoms.get_calculator() assert pot is not None forces = [] for scell in supercells: matoms = phonopy_to_matdb(scell) #Call a manual reset of the calculator so that we explicitly recalculate #the forces for the current atoms object. pot.reset() matoms.set_calculator(pot) forces.append(matoms.get_forces()) phonon.set_forces(forces) phonon.produce_force_constants() return unroll_fc(phonon._force_constants)
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 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_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]]) 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) nac_params['method'] = 'wang' phonon.set_nac_params(nac_params) return phonon
def get_force_constants_from_phonopy(**kwargs): """ Calculate the force constants using phonopy :param kwargs: :return: """ from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import Phonopy import numpy as np # print 'function',kwargs 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'], distance=phonopy_input['distance']) 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']): forces = kwargs.pop('forces_{}'.format(i)).get_array('forces')[0] first_atoms['forces'] = np.array(forces, dtype='double', order='c') # LOCAL calculation # Calculate and get force constants phonon.set_displacement_dataset(data_sets) phonon.produce_force_constants() force_constants = phonon.get_force_constants() array_data = ArrayData() array_data.set_array('force_constants', force_constants) return {'array_data': array_data}
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 _get_phononobject_phonopy(self, structure, potential, smat, save_parameters, path, displacement_distance=0.01): cell = get_phonopy_structure(structure) phonon = Phonopy(cell, smat, primitive_matrix=[[1.0, 0.0, 0.0], [0.0, 1, 0.0], [0., 0., 1.0]], factor=VaspToTHz) # displacements phonon.generate_displacements(distance=displacement_distance) print("[Phonopy] Atomic displacements:") disps = phonon.get_displacements() for d in disps: print("[Phonopy] %d %s" % (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) cell.set_calculator(potential) # this part is adapted from: https://web.archive.org/web/20200610084959/https://github.com/phonopy/phonopy/blob/develop/example/ase/8Si-phonon.py # Copyright by Atsushi Togo forces = cell.get_forces() drift_force = forces.sum(axis=0) print( ("[Phonopy] Drift force:" + "%11.5f" * 3) % tuple(drift_force)) for force in forces: force -= drift_force / forces.shape[0] set_of_forces.append(forces) phonon.produce_force_constants(forces=set_of_forces) if save_parameters: phonon.save(path) return phonon
def get_phonon(self) -> Phonopy: """ Get phonopy object. Returns: Phonopy: Phonopy class object. """ phonon = Phonopy( get_phonopy_structure(self._unitcell), supercell_matrix=self._phonon_setting_info['supercell_matrix'], primitive_matrix=self._phonon_setting_info['primitive_matrix'], nac_params=self._nac_params, ) phonon.set_displacement_dataset( self._phonon_setting_info['displacement_dataset']) phonon.set_forces(self._force_sets) phonon.produce_force_constants() return phonon
def get_phonon_from_phonolammps(phonolammps) -> Phonopy: """ Get Phonopy class object from PhonoLammps. Args: phonolammps: Phonlammps class object. """ unitcell = phonolammps.get_unitcell() force_constants = phonolammps.get_force_constants() supercell_matrix = phonolammps.get_supercell_matrix() primitive_matrix = phonolammps.get_primitve_matrix() phonon = Phonopy(unitcell=unitcell, primitive_matrix=primitive_matrix, supercell_matrix=supercell_matrix) dataset = phonolammps.get_force_constants(include_data_set=True)[1] phonon.dataset = dataset phonon.produce_force_constants() return phonon
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
def get_force_constants_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) print bulk print 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] # Calculate and get force constants phonon.set_displacement_dataset(data_sets) phonon.produce_force_constants() # force_constants = phonon.get_force_constants().tolist() force_constants = phonon.get_force_constants() # Set force sets and force constants array to return data = ArrayData() data.set_array('force_sets', np.array(data_sets)) data.set_array('force_constants', force_constants) return {'phonopy_output': data}
def get_random_displacements(structure, number_of_snapshots, temperature, phonon_setting_info, dataset_for_fc, random_seed=None): """Generate supercells with random displacemens The random displacements are generated from phonons and harmonic oscillator distribution function of canonical ensemble. The input phonons are calculated from force constants calculated from forces and displacemens of the supercell snapshots in previous phonon calculation steps. Returns ------- dataset : Dict Displacement datasets to run force calculations. """ # Calculate force constants by fitting using ALM smat = phonon_setting_info['supercell_matrix'] ph = Phonopy(phonopy_atoms_from_structure(structure), supercell_matrix=smat, primitive_matrix='auto') d = dataset_for_fc.get_array('displacements') f = dataset_for_fc.get_array('forces') ph.dataset = {'displacements': d, 'forces': f} ph.produce_force_constants(fc_calculator='alm') if random_seed is not None: _random_seed = random_seed.value else: _random_seed = None dataset = _generate_random_displacements(ph, number_of_snapshots.value, temperature.value, random_seed=_random_seed) return Dict(dict=dataset)
def get_frequency(poscar_filename, force_sets): """Calculate phonons and return frequencies.""" unitcell = read_vasp(poscar_filename) volume = unitcell.volume 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]], ) disps = np.zeros_like(force_sets) disps[0] = [0.01, 0, 0] phonon.dataset = { "natom": len(force_sets), "first_atoms": [{ "number": 0, "displacement": [0.01, 0, 0], "forces": force_sets }], } phonon.produce_force_constants() return phonon.get_frequencies([0.5, 0.5, 0]), volume
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
def runSimulation(self): starting_struct = singleFromFile(self.args) relaxed_struct = runCalc("all_relax", ["structures"], [starting_struct], self.args)["structures"][0] phonopy_struct = get_phonopy_structure(relaxed_struct) supercell_matrix = 3 * eye(3) phonon = Phonopy(phonopy_struct, supercell_matrix) phonon.generate_displacements(distance=0.01) supercells = phonon.supercells_with_displacements phonon_structs = [get_pmg_structure(struct) for struct in supercells] forces = runCalc("all_static", ["forces"], phonon_structs, self.args)["forces"] phonon.set_forces(array(forces)) phonon.produce_force_constants() phonon.symmetrize_force_constants() self.plotter = PhononBSPlotter( get_phonon_band_structure_symm_line_from_fc( relaxed_struct, supercell_matrix, phonon.force_constants))
def obtain_phonon_dispersion_spectra(structure, bands_ranges, NAC=False, band_resolution=30): print("Calculating phonon dispersion spectra...") 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, ) if NAC: print("Phonopy warning: Using Non Analitical Corrections") print("BORN file is needed to do this") get_is_symmetry = True # sfrom 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() bands = [] for q_start, q_end in bands_ranges: band = [] for i in range(band_resolution + 1): band.append(np.array(q_start) + (np.array(q_end) - np.array(q_start)) / band_resolution * i) bands.append(band) phonon.set_band_structure(bands) return phonon.get_band_structure()
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.set_displacement_dataset(force_sets) phonon.produce_force_constants() return phonon
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")
np.array(q_start)) / 50 * i band.append(points.tolist()) 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): print(("%5.2f %5.2f %5.2f " + (" %7.3f" * len(freq))) % ((q[0], q[1], q[2]) + tuple(freq))) print(((" " * 18) + (" %7.3f" * len(g))) % tuple(g)) bands: List[List] = [] _append_band(bands, [0.5, 0.5, 0.0], [0.0, 0.0, 0.0]) _append_band(bands, [0.0, 0.0, 0.0], [0.5, 0.5, 0.5])
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) cell.set_calculator(calc) forces = cell.get_forces() drift_force = forces.sum(axis=0) print "[Phonopy] Drift force:", "%11.5f"*3 % tuple(drift_force) # Simple translational invariance for force in forces: force -= drift_force / forces.shape[0] set_of_forces.append(forces) # Phonopy post-process phonon.produce_force_constants(forces=set_of_forces) print print "[Phonopy] Phonon frequencies at Gamma:" for i, freq in enumerate(phonon.get_frequencies((0, 0, 0))): print "[Phonopy] %3d: %10.5f THz" % (i + 1, freq) # THz
def phonons(self, atoms=None, lammps_cmd="", enforce_c_size=15.0, parameters={}): """Make Phonon calculation setup.""" from phonopy import Phonopy from phonopy.file_IO import ( # parse_FORCE_CONSTANTS, write_FORCE_CONSTANTS, ) bulk = atoms.phonopy_converter() dim = get_supercell_dims(atoms, enforce_c_size=enforce_c_size) atoms = atoms.make_supercell([dim[0], dim[1], dim[2]]) Poscar(atoms).write_file("POSCAR") atoms = atoms.make_supercell_matrix([dim[0], dim[1], dim[2]]) Poscar(atoms).write_file("POSCAR-Super.vasp") phonon = Phonopy(bulk, [[dim[0], 0, 0], [0, dim[1], 0], [0, 0, dim[2]]]) print("[Phonopy] Atomic displacements1:", bulk) print("[Phonopy] Atomic displacements2:", phonon, dim[0], dim[1], dim[2]) phonon.generate_displacements(distance=0.03) disps = phonon.get_displacements() print("[Phonopy] Atomic displacements3:", disps) for d in disps: print("[Phonopy]", d[0], d[1:]) supercells = phonon.get_supercells_with_displacements() # Force calculations by calculator set_of_forces = [] disp = 0 from ase import Atoms as AseAtoms for scell in supercells: ase_atoms = AseAtoms( symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True, ) j_atoms = ase_to_atoms(ase_atoms) disp = disp + 1 parameters["control_file"] = "run0.mod" a, b, forces = LammpsJob( atoms=j_atoms, lammps_cmd=lammps_cmd, parameters=parameters, jobname="disp-" + str(disp), ).runjob() print("forces=", forces) drift_force = forces.sum(axis=0) print("drift forces=", drift_force) # Simple translational invariance for force in forces: force -= drift_force / forces.shape[0] set_of_forces.append(forces) phonon.produce_force_constants(forces=set_of_forces) write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS") print() print("[Phonopy] Phonon frequencies at Gamma:")
def load_phonopy(filename, structure, dim, symprec=0.01, primitive_matrix=None, factor=VaspToTHz, symmetrise=True, born=None, write_fc=False): """Load phonopy output and return an ``phonopy.Phonopy`` object. Args: filename (str): Path to phonopy output. Can be any of ``FORCE_SETS``, ``FORCE_CONSTANTS``, or ``force_constants.hdf5``. structure (:obj:`~pymatgen.core.structure.Structure`): The unitcell structure. dim (list): The supercell size, as a :obj:`list` of :obj:`float`. symprec (:obj:`float`, optional): The tolerance for determining the crystal symmetry. primitive_matrix (:obj:`list` or :obj:`str`, optional): The transformation matrix from the conventional to primitive cell. Only required when the conventional cell was used as the starting structure. Should be provided as a 3x3 :obj:`list` of :obj:`float`. Alternatively the str 'auto' may be provided. factor (:obj:`float`, optional): The conversion factor for phonon frequency. Defaults to :obj:`phonopy.units.VaspToTHz`. symmetrise (:obj:`bool`, optional): Symmetrise the force constants. Defaults to ``True``. born (:obj:`str`, optional): Path to file containing Born effective charges. Should be in the same format as the file produced by the ``phonopy-vasp-born`` script provided by phonopy. write_fc (:obj:`bool` or :obj:`str`, optional): Write the force constants to disk. If ``True``, a ``FORCE_CONSTANTS`` file will be written. Alternatively, if set to ``"hdf5"``, a ``force_constants.hdf5`` file will be written. Defaults to ``False`` (force constants not written). """ unitcell = get_phonopy_structure(structure) num_atom = unitcell.get_number_of_atoms() num_satom = determinant(dim) * num_atom phonon = Phonopy(unitcell, dim, primitive_matrix=primitive_matrix, factor=factor, symprec=symprec) if 'FORCE_CONSTANTS' == filename or '.hdf5' in filename: # if force constants exist, use these to avoid recalculating them if '.hdf5' in filename: fc = file_IO.read_force_constants_hdf5(filename) elif 'FORCE_CONSTANTS' == filename: fc = file_IO.parse_FORCE_CONSTANTS(filename=filename) if fc.shape[0] != num_satom: msg = ("\nNumber of atoms in supercell is not consistent with the " "matrix shape of\nforce constants read from {}.\nPlease" "carefully check --dim.") logging.error(msg.format(filename)) sys.exit() phonon.set_force_constants(fc) elif 'FORCE_SETS' == filename: # load the force sets from file and calculate force constants fs = file_IO.parse_FORCE_SETS() if fs['natom'] != num_satom: msg = ("\nNumber of atoms in supercell is not consistent with the " "the data in FORCE_SETS\nPlease carefully check --dim.") logging.error(msg.format(filename)) sys.exit() phonon.set_displacement_dataset(fs) logging.info("Calculating force constants...") phonon.produce_force_constants() if born: # load born parameters from a file nac_params = file_IO.parse_BORN(phonon._primitive, symprec=symprec, filename=born) # set the nac unit conversion factor manual, specific to VASP nac_params['factor'] = Hartree * Bohr phonon.set_nac_params(nac_params) if symmetrise: phonon.symmetrize_force_constants() if write_fc == 'hdf5': file_IO.write_force_constants_to_hdf5(phonon.get_force_constants()) logging.info("Force constants written to force_constants.hdf5.") elif write_fc: file_IO.write_FORCE_CONSTANTS(phonon.get_force_constants()) logging.info("Force constants written to FORCE_CONSTANTS.") return phonon
def phonopy_run(phonon, single=True, filename='FORCE_SETS'): """Run the phonon calculations, using PhonoPy. The force constants are then stored in the Phonon ASE object. input: phonon: ASE Phonon object with Atoms and Calculator single: when True, the forces are computed only for a single step, and then exit. This allows to split the loop in independent iterations. When calling again the 'run' method, already computed steps are ignored, missing steps are completed, until no more are needed. When set to False, all steps are done in a row. output: True when a calculation step was performed, False otherwise or no more is needed. nb_of_iterations: the number of steps remaining """ from phonopy import Phonopy from phonopy.structure.atoms import Atoms as PAtoms from phonopy.structure.atoms import PhonopyAtoms import phonopy.file_IO as file_IO # we first look if an existing phonon pickle exists. This is the case if we # are running with iterative calls while return value is True. The first call # will then create the objects, which are subsequently updated until False. # Set calculator if provided # assert phonon.calc is not None, "Provide calculator in Phonon __init__ method" # Atoms in the supercell -- repeated in the lattice vector directions # beginning with the last supercell = phonon.atoms * phonon.N_c # create a PhonopyAtoms object cell = PhonopyAtoms(phonon.atoms.get_chemical_symbols(), positions=phonon.atoms.get_positions(), cell=phonon.atoms.get_cell(), magmoms=None) # is there an existing PhonoPy calculation ? # using factor=6.46541380e-2=VaspToeV if os.path.exists('FORCE_SETS'): phonpy = Phonopy(cell, numpy.diag(phonon.N_c), primitive_matrix=None, dynamical_matrix_decimals=None, force_constants_decimals=None, symprec=1e-05, is_symmetry=True, use_lapack_solver=False, log_level=1) force_sets = file_IO.parse_FORCE_SETS(filename='FORCE_SETS') phonpy.set_displacement_dataset(force_sets) # inactivate magmoms in supercell as some calculators do not provide that phonpy._supercell.magmoms = None phonpy.produce_force_constants(calculate_full_force_constants=False) else: # create a PhonoPy Phonon object. phonpy = Phonopy(cell, numpy.diag(phonon.N_c)) # generate displacements (minimal set) phonpy.generate_displacements(distance=0.01) # iterative call for all displacements set_of_forces, flag, nb_of_iterations = phonopy_run_calculate( phonon, phonpy, supercell, single) if flag is True: return nb_of_iterations # some more work is required sys.stdout.write('[ASE/Phonopy] Computing force constants\n') # use symmetry to derive forces in equivalent displacements phonpy.produce_force_constants(forces=set_of_forces) # generate disp.yaml and FORCE_SETS (for later use) displacements = phonpy.get_displacements() directions = phonpy.get_displacement_directions() file_IO.write_disp_yaml(displacements, phonpy.get_supercell(), directions=directions) file_IO.write_FORCE_SETS(phonpy.get_displacement_dataset()) # store as additional data in atoms 'info' phonon.atoms.info["phonopy"] = phonpy # save the PhonoPy object fid = opencew("phonopy.pkl") if fid is not None and rank == 0: print("[ASE/Phonopy] Writing %s" % "phonopy.pkl") pickle.dump(phonpy, fid, protocol=2) fid.close() # transfer results to the ASE phonon object # Number of atoms (primitive cell) natoms = len(phonon.indices) # Number of unit cells (supercell) N = numpy.prod(phonon.N_c) # Phonopy: force_constants size is [N*natoms,N*natoms,3,3] # Phi[i,j,a,b] with [i,j = atom in supercell] and [a,b=xyz] force_constants = phonpy.get_force_constants() # the atoms [i] which are moved are in the first cell of the supercell, i.e.Ni=0 # the forces are then stored for all atoms [Nj,j] as [3,3] matrices # we compute the sum on all supercells, which all contain n atoms. C_N = numpy.zeros((N, 3 * natoms, 3 * natoms), dtype=complex) Ni = 0 for Nj in range(N): for ni in range(natoms): Nni = ni for nj in range(natoms): # compute Nn indices Nnj = Nj * natoms + nj # get fc 3x3 matrix C_N[Nj, (3 * ni):(3 * ni + 3), (3 * nj):(3 * nj + 3)] += force_constants[Nni][Nnj] # convert to ASE storage # ASE: phonon.C_N size is be [N, 3*natoms, 3*natoms] # Phi[i,j] = Phi[j,i] phonon.C_N = C_N # fill dynamical matrix (mass prefactor) phonon.D_N = phonon.C_N.copy() # Add mass prefactor m_a = phonon.atoms.get_masses() phonon.m_inv_x = numpy.repeat(m_a[phonon.indices]**-0.5, 3) M_inv = numpy.outer(phonon.m_inv_x, phonon.m_inv_x) for D in phonon.D_N: D *= M_inv return 0 # nothing left to do