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 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 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 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 create_supercells_with_displacements_using_phonopy(structure, ph_settings): """ Use phonopy to create the supercells with displacements to calculate the force constants by using finite displacements methodology :param structure: StructureData object :param phonopy_input: ParametersData object containing a dictionary with the data needed for phonopy :return: A set of StructureData Objects containing the supercells with displacements """ from phonopy import Phonopy # Generate phonopy phonon object phonon = Phonopy(phonopy_bulk_from_structure(structure), supercell_matrix=ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_precision) phonon.generate_displacements(distance=ph_settings.dict.distance) cells_with_disp = phonon.get_supercells_with_displacements() # Transform cells to StructureData and set them ready to return data_sets = phonon.get_displacement_dataset() data_sets_object = ForceSetsData(data_sets=data_sets) disp_cells = {'data_sets': data_sets_object} 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_displaced_structures(pmg_structure, atom_disp=0.01, supercell_matrix=None, yaml_fname=None, **kwargs): r""" 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() write_disp_yaml( displacements=displacements, supercell=phonon.get_supercell(), 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 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_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 _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 create_supercells_with_displacements_using_phonopy(structure, phonopy_input): """ Create the supercells with the displacements to use the finite displacements methodology to calculate the force constants :param structure: Aiida StructureData Object :param phonopy_input: Aiida Parametersdata object containing a dictionary with the data needed to run phonopy: supercells matrix, primitive matrix and displacement distance. :return: dictionary of Aiida StructureData Objects containing the cells with displacements """ from phonopy.structure.atoms import Atoms as PhonopyAtoms from phonopy import Phonopy import numpy as np # 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) phonopy_input = phonopy_input.get_dict() phonon = Phonopy(bulk, phonopy_input['supercell'], primitive_matrix=phonopy_input['primitive']) 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 data_sets = phonon.get_displacement_dataset() data_sets_object = ArrayData() for i, first_atoms in enumerate(data_sets['first_atoms']): data_sets_array = np.array([ first_atoms['direction'], first_atoms['number'], first_atoms['displacement'] ]) data_sets_object.set_array('data_sets_{}'.format(i), data_sets_array) disp_cells = {'data_sets': data_sets_object} 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_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_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: phonon.generate_displacements(distance=disp) supercells = phonon.get_supercells_with_displacements() for (i, scell) in enumerate(supercells): at = Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True) at.set_calculator(calc) energy = at.get_potential_energy(force_consistent=True) forces = at.get_forces() stress = at.get_stress(voigt=False) 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] at.arrays["force"] = forces at.info["virial"] = -1.0 * at.get_volume() * stress at.info["energy"] = energy at.info["config_type"] = "PH_" + config_type write("PH_{}_{}_scell_{}.xyz".format(config_type, i, disp), at) al.append(at) return al
class PhononFromModel(object): """ This class uses frozen phonon method to calculate the phonon dispersion curves and thermodynamic properties of a structure. The steps are as follows: 1. Displaced structures are obtained from pristine structure via phonopy. 2. The forces of each displaced structures are calculated by model 3. The forces are passed to phonopy object and the force constant are produced 4. Phonon is calculated once the force constant matrix is available. Args: model (model object): a model object that has a method "calculate_forces" that takes in a list of structures and return a list of N*3 forces, where N are the number of atoms in each structures structure (pymatgen structure): a pristine pymatgen structure atom_disp (float): small displacements in Angstrom """ 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 get_thermo_properties(self, mesh=[8, 8, 8], t_step=10, t_max=3000, t_min=0): self.phonon.set_mesh(mesh=mesh) self.phonon.set_thermal_properties(t_step=t_step, t_max=t_max, t_min=t_min) plt = self.phonon.plot_thermal_properties() return plt def get_bs_plot(self, points_per_line=50, figsize=(6, 4), ylim=[-1, 5]): bands = [] bands = append_bands(bands, self.qpoints, points_per_line) self.phonon.set_band_structure(bands) q_points, self.distances, self.frequencies, eigvecs = self.phonon.get_band_structure() special_points = self.phonon._band_structure._special_points distance = self.phonon._band_structure._distance plt.figure(figsize=figsize) for j, (d, f) in enumerate(zip(self.distances, self.frequencies)): for i, freqs in enumerate(f.T): if i == 0 and j == 0: plt.plot(d, freqs, "b-", lw=1) else: plt.plot(d, freqs, "b-", lw=1) for sp in special_points: plt.axvline(x=sp, linestyle=':', linewidth=1, color='k') plt.axhline(y=0, linestyle=':', linewidth=1, color='k') plt.xticks(special_points, ["$\mathrm{%s}$" % i for i in self.vertices]) plt.xlabel("Wave vector") plt.ylabel("Frequency (THz)") plt.xlim(0, distance) plt.ylim(ylim) plt.yticks(list(range(ylim[0], ylim[-1]+1))) plt.tight_layout() return plt
def get_phonon_distrib_alist( prim_cell, NNN, T, seed_range, calc, cp_files=None, plus_minus=True, delta=0.01, ): """ prim_cell (str) ASE readable primitive unitcell structure file. NNN (list of int, shape: (3,3)) Supercell matrix used to calculate force constants. T (float) Temperature in Kelvin unit. seed_range (range or list of int) Seeds for random number generation. calc (str, choices: ('lmp', 'vasp')) Calculator for force calculation. cp_files (list of str) List of input files for force calculation. plus_minus (bool) Option handed to ASE function. delta (float) Displacement in Angstrom for finite displacement method. """ # Main from ase.io import read, write atoms = read(prim_cell) from phonopy import Phonopy phonon = Phonopy( atoms, NNN, ) phonon.generate_displacements( delta, ) pho_super = phonon.get_supercell() pho_disp = phonon.get_supercells_with_displacements() from phonopy.interface import vasp vasp.write_supercells_with_displacements( pho_super, pho_disp, ) import ss_phonopy as ssp phonon = ssp.calc_phonon( calc, phonon, cp_files=cp_files, ) masses = pho_super.masses job_name = 'eig_x{}{}{}_d{:5.3f}_sym{}'.format(NNN[0][0], NNN[1][1], NNN[2][2], delta, phonon._is_symmetry) try: e_s = np.load('{}.npz'.format(job_name)) except: print('Failed to load {}.npz file. Start to solve eigen problem.'.format(job_name)) eigen_set = get_eigen_set( phonon.get_force_constants(), masses, ) np.savez('{}.npz'.format(job_name), w2=eigen_set[0], D=eigen_set[1]) else: print('Successfully loaded {}.npz file!'.format(job_name)) eigen_set = (e_s['w2'], e_s['D']) from ase.md.velocitydistribution import phonon_harmonics from ase import Atoms, units alist = [] for i in seed_range: d_ac, v_ac = phonon_harmonics( None, masses, T *units.kB, eigen_set=eigen_set, # rng=np.random.rand, seed=i, quantum=True, plus_minus=plus_minus, # return_eigensolution=False, # failfast=True, ) new_super = Atoms( cell = pho_super.get_cell(), symbols = pho_super.get_chemical_symbols(), positions = pho_super.get_positions() + d_ac, velocities = v_ac, pbc = True, ) alist.append(new_super) return(alist)
relax.run(fmax=fmax) Unit_cell = api_ph.aseAtoms_to_phonopyAtoms(ucell_ase) Intf_vasp.write_vasp('POSCAR_relx', Unit_cell) else: Unit_cell = Intf_vasp.read_vasp( "POSCAR") # read prim cell from the POSCAR file # generate displacements prim_mat = np.eye(3) #[[0, 0.5, 0.5],[0.5, 0, 0.5],[0.5, 0.5, 0]] phonon_scell = Phonopy( Unit_cell, np.diag(Ncells), primitive_matrix=prim_mat) # generate an phononpy object for LD calc. phonon_scell.generate_displacements(distance=0.03) # vasp Scells_phonopy = phonon_scell.get_supercells_with_displacements( ) # This returns a list of Phononpy atoms object # convert phonopy atoms objects to quippy atom objects Scells_quippy = [] for scell in Scells_phonopy: scell_qp = api_ph.phonopyAtoms_to_aseAtoms(scell) Scells_quippy.append(scell_qp) # calculate forces and convert to phonopy force_sets force_gap_scells = api_q.calc_force_sets_GAP(gp_xml_file, Scells_quippy) #parse force set and calc force constants phonon_scell.set_forces(force_gap_scells) PhonIO.write_FORCE_SETS(phonon_scell.get_displacement_dataset() ) # write forces & displacements to FORCE_SET force_set = PhonIO.parse_FORCE_SETS() # parse force_sets
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 calculate_phonon(atoms, calc, ndim=np.eye(3), primitive_matrix=np.eye(3), distance=0.01, factor=VaspToTHz, is_symmetry=True, symprec=1e-5, func=None, **func_args): """ """ if 'magmoms' in atoms.arrays: is_mag = True else: is_mag = False # 1. get displacements and supercells atoms.set_calculator(calc) # bulk = PhonopyAtoms(atoms=atoms) if is_mag: bulk = PhonopyAtoms( symbols=atoms.get_chemical_symbols(), scaled_positions=atoms.get_scaled_positions(), cell=atoms.get_cell(), magmoms=atoms.arrays['magmoms'], ) else: bulk = PhonopyAtoms(symbols=atoms.get_chemical_symbols(), scaled_positions=atoms.get_scaled_positions(), cell=atoms.get_cell()) phonon = Phonopy(bulk, ndim, primitive_matrix=primitive_matrix, factor=factor, symprec=symprec) phonon.generate_displacements(distance=distance) disps = phonon.get_displacements() for d in disps: print("[phonopy] %d %s" % (d[0], d[1:])) supercell0 = phonon.get_supercell() supercells = phonon.get_supercells_with_displacements() write_supercells_with_displacements(supercell0, supercells) write_disp_yaml(disps, supercell0) # 2. calculated forces. set_of_forces = [] for iscell, scell in enumerate(supercells): cell = Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True) if is_mag: cell.set_initial_magnetic_moments( atoms.get_initial_magnetic_moments()) cell.set_calculator(calc) dir_name = "PHON_CELL%s" % iscell cur_dir = os.getcwd() if not os.path.exists(dir_name): os.mkdir(dir_name) os.chdir(dir_name) forces = cell.get_forces() #print "[Phonopy] Forces: %s" % forces # Do something other than calculating the forces with func. # func: func(atoms, calc, func_args) if func is not None: func(cell, calc, **func_args) os.chdir(cur_dir) 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) force_constants = phonon.get_force_constants() write_FORCE_CONSTANTS(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 print("[Phonopy] %3d: %10.5f cm-1" % (i + 1, freq * 33.35)) #cm-1 return phonon
def calculate_phonon(atoms, calc=None, forces_set_file=None, ndim=np.eye(3), primitive_matrix=np.eye(3), distance=0.01, factor=VaspToTHz, is_plusminus='auto', is_symmetry=True, symprec=1e-5, func=None, prepare_initial_wavecar=False, skip=None, restart=True, parallel=True, sc_mag=None, **func_args): """ """ if 'magmoms' in atoms.arrays or 'initial_magmoms' in atoms.arrays: is_mag = True else: is_mag = False print("is_mag: ", is_mag) # 1. get displacements and supercells if calc is not None: atoms.set_calculator(calc) # bulk = PhonopyAtoms(atoms=atoms) if is_mag: bulk = PhonopyAtoms( symbols=atoms.get_chemical_symbols(), scaled_positions=atoms.get_scaled_positions(), cell=atoms.get_cell(), magmoms=atoms.arrays['initial_magmoms'], ) else: bulk = PhonopyAtoms(symbols=atoms.get_chemical_symbols(), scaled_positions=atoms.get_scaled_positions(), cell=atoms.get_cell()) phonon = Phonopy(bulk, ndim, primitive_matrix=primitive_matrix, factor=factor, symprec=symprec) phonon.generate_displacements(distance=distance, is_plusminus=is_plusminus) disps = phonon.get_displacements() for d in disps: print(("[phonopy] %d %s" % (d[0], d[1:]))) supercell0 = phonon.get_supercell() supercells = phonon.get_supercells_with_displacements() #write_supercells_with_displacements(supercell0, supercells) write_disp_yaml(disps, supercell0) # 2. calculated forces. if forces_set_file is not None: symmetry = phonon.get_symmetry() set_of_forces = parse_FORCE_SETS( is_translational_invariance=False, filename=forces_set_file) # ['first_atoms'] # set_of_forces=np.array(set_of_forces) #set_of_forces=[np.asarray(f) for f in set_of_forces] phonon.set_displacement_dataset(set_of_forces) phonon.produce_force_constants() else: # initialize set of forces if restart and os.path.exists('forces_set.pickle'): try: with open("forces_set.pickle", 'rb') as myfile: set_of_forces = pickle.load(myfile) iskip = len(set_of_forces) - 1 except: set_of_forces = [] iskip = -1 else: set_of_forces = [] iskip = -1 if prepare_initial_wavecar and skip is None: scell = supercell0 cell = Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True) if is_mag: cell.set_initial_magnetic_moments(sc_mag) write('Supercell.cif', cell) mcalc = copy.deepcopy(calc) mcalc.set(lwave=True, lcharg=True) cell.set_calculator(mcalc) dir_name = "SUPERCELL0" cur_dir = os.getcwd() if not os.path.exists(dir_name): os.mkdir(dir_name) os.chdir(dir_name) mcalc.scf_calculation(cell) os.chdir(cur_dir) def calc_force(iscell): scell = supercells[iscell] cell = Atoms(symbols=scell.get_chemical_symbols(), scaled_positions=scell.get_scaled_positions(), cell=scell.get_cell(), pbc=True) if is_mag: cell.set_initial_magnetic_moments(sc_mag) cell.set_calculator(copy.deepcopy(calc)) dir_name = "PHON_CELL%s" % iscell cur_dir = os.getcwd() if not os.path.exists(dir_name): os.mkdir(dir_name) if prepare_initial_wavecar: os.system('ln -s %s %s' % (os.path.abspath("SUPERCELL0/WAVECAR"), os.path.join(dir_name, 'WAVECAR'))) os.chdir(dir_name) forces = cell.get_forces() print("[Phonopy] Forces: %s" % forces) # Do something other than calculating the forces with func. # func: func(atoms, calc, func_args) if func is not None: func(cell, calc, **func_args) os.chdir(cur_dir) 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] return forces if parallel: p = Pool() set_of_forces = p.map(calc_force, list(range(iskip, len(supercells)))) else: for iscell, scell in enumerate(supercells): if iscell > iskip: fs = calc_force(iscell) set_of_forces.append(fs) with open("forces_set.pickle", 'wb') as myfile: pickle.dump(set_of_forces, myfile) phonon.produce_force_constants(forces=np.array(set_of_forces)) force_constants = phonon.get_force_constants() write_FORCE_CONSTANTS(force_constants, filename='FORCE_CONSTANTS') #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 # print(("[Phonopy] %3d: %10.5f cm-1" % (i + 1, freq * 33.35))) #cm-1 with open('phonon.pickle', 'wb') as myfile: pickle.dump(phonon, myfile) phonon.save(settings={'force_constants': True}) return phonon
phonon = Phonopy( atoms, # [[N,0,0],[0,N,0],[0,0,N]], NNN, # primitive_matrix = [[0.5,0.5,0],[0,0.5,0.5],[0.5,0,0.5]], primitive_matrix=primitive_matrix, nac_params=nac_params, factor=factor, is_symmetry=is_symmetry, ) phonon.generate_displacements( distance=delta, is_plusminus=is_plusminus, ) pho_disp = phonon.get_supercells_with_displacements() vasp.write_supercells_with_displacements( phonon.get_supercell(), pho_disp, ) ######### get new phonon object ########## # import ss_phonopy as ssp phonon = ssp.calc_phonon( calc, phonon, acoustic_sum_rule=acou_sum_rule, rot_sum_rule=rot_sum_rule, r_cut=r_cut,
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) 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]