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 _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 _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 _phonons_allclose(self, ph, fc333): ph333 = Phonopy(ph.unitcell, supercell_matrix=[3, 3, 3], primitive_matrix=ph.primitive_matrix) ph333.force_constants = fc333 ph333.nac_params = ph.nac_params comm_points = self._get_comm_points(ph) ph.run_qpoints(comm_points) ph333.run_qpoints(comm_points) np.testing.assert_allclose(ph.get_qpoints_dict()['frequencies'], ph333.get_qpoints_dict()['frequencies'], atol=1e-5)
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 generate_displacements(self): label = 'force_constants_%d' % self.ctx.iteration fc_array = self.ctx[label].outputs.force_constants fc = fc_array.get_array('force_constants') phonon_setting_info = self.inputs.phonon_settings smat = phonon_setting_info['supercell_matrix'] ph = Phonopy(phonopy_atoms_from_structure(self.inputs.structure), supercell_matrix=smat, primitive_matrix='auto') ph.force_constants = fc if 'random_seed' in self.inputs: random_seed = self.inputs.random_seed.value else: random_seed = None dataset = _generate_random_displacements( ph, self.inputs.number_of_snapshots.value, self.inputs.temperature.value, random_seed=random_seed) self.ctx.dataset = Dict(dict=dataset)
def load_phonopy( filename, structure, dim, symprec=1e-5, 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" in 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" in 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.force_constants = fc elif "FORCE_SETS" in filename: # load the force sets from file and calculate force constants fs = file_IO.parse_FORCE_SETS(filename=filename) 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.dataset = fs logging.info("Calculating force constants...") phonon.produce_force_constants() if symmetrise: phonon.symmetrize_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.nac_params = nac_params if write_fc == "hdf5": file_IO.write_force_constants_to_hdf5(phonon.force_constants) logging.info("Force constants written to force_constants.hdf5.") elif write_fc: file_IO.write_FORCE_CONSTANTS(phonon.force_constants) logging.info("Force constants written to FORCE_CONSTANTS.") return phonon