def _set_force_constants(phonon, force_constants_filename, force_sets_filename, use_alm): natom = phonon.supercell.get_number_of_atoms() if force_constants_filename is not None: dot_split = force_constants_filename.split('.') p2s_map = phonon.primitive.get_primitive_to_supercell_map() if len(dot_split) > 1 and dot_split[-1] == 'hdf5': fc = read_force_constants_hdf5(filename=force_constants_filename, p2s_map=p2s_map) else: fc = parse_FORCE_CONSTANTS(filename=force_constants_filename, p2s_map=p2s_map) phonon.set_force_constants(fc) elif force_sets_filename is not None: force_sets = parse_FORCE_SETS(natom=natom, filename=force_sets_filename) if force_sets: phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants( calculate_full_force_constants=False, use_alm=use_alm) elif os.path.isfile("FORCE_SETS"): force_sets = parse_FORCE_SETS(natom=natom) if force_sets: phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants( calculate_full_force_constants=False, use_alm=use_alm)
def load(supercell_matrix, primitive_matrix=None, nac_params=None, unitcell=None, calculator="vasp", unitcell_filename=None, born_filename=None, force_sets_filename=None, force_constants_filename=None, factor=VaspToTHz, frequency_scale_factor=None, symprec=1e-5, is_symmetry=True, log_level=0): if unitcell is None: _unitcell, _ = read_crystal_structure(filename=unitcell_filename, interface_mode=calculator) else: _unitcell = unitcell # units keywords: factor, nac_factor, distance_to_A units = get_default_physical_units(calculator) phonon = Phonopy(_unitcell, supercell_matrix, primitive_matrix=primitive_matrix, factor=units['factor']) if nac_params is None: if born_filename is None: _nac_params = None else: _nac_params = parse_BORN(phonon.primitive, filename=born_filename) else: _nac_params = nac_params if _nac_params is not None: if _nac_params['factor'] is None: _nac_params['factor'] = units['nac_factor'] phonon.set_nac_params(_nac_params) if force_constants_filename is not None: dot_split = force_constants_filename.split('.') p2s_map = phonon.primitive.get_primitive_to_supercell_map() if len(dot_split) > 1 and dot_split[-1] == 'hdf5': fc = read_force_constants_hdf5(filename=force_constants_filename, p2s_map=p2s_map) else: fc = parse_FORCE_CONSTANTS(filename=force_constants_filename, p2s_map=p2s_map) phonon.set_force_constants(fc) elif force_sets_filename is not None: force_sets = parse_FORCE_SETS(filename=force_sets_filename) phonon.set_displacement_dataset(force_sets) phonon.produce_force_constants() return phonon
def read_force_constants_from_hdf5(filename='force_constants.hdf5', p2s_map=None, calculator=None): fc = read_force_constants_hdf5(filename=filename, p2s_map=p2s_map) fc_unit = read_physical_unit_in_force_constants_hdf5(filename=filename) if fc_unit is None: return fc else: factor = get_force_constant_conversion_factor(fc_unit, calculator) return fc * factor
def read_force_constants_from_hdf5(filename='force_constants.hdf5', p2s_map=None, calculator=None): """Convert force constants physical unit Each calculator interface has own default force constants physical unit. This method reads the physical unit of force constants if it exists and if the read physical unit is different from the default one, the force constants values are converted to have the default physical units. Note ---- This method is also used from phonopy script. """ fc = read_force_constants_hdf5(filename=filename, p2s_map=p2s_map) fc_unit = read_physical_unit_in_force_constants_hdf5(filename=filename) if fc_unit is None: return fc else: factor = get_force_constant_conversion_factor(fc_unit, calculator) return fc * factor
def read_force_constants_from_hdf5(filename="force_constants.hdf5", p2s_map=None, calculator=None): """Convert force constants physical unit. Each calculator interface has own default force constants physical unit. This method reads 'physical_unit' in force constants hdf5 file and if this is different from the one for 'calculator', the force constants are converted to have the physical unit of the calculator. Note ---- This method is also used from phonopy script. """ fc, fc_unit = read_force_constants_hdf5(filename=filename, p2s_map=p2s_map, return_physical_unit=True) if fc_unit is None: return fc else: factor = get_force_constant_conversion_factor(fc_unit, calculator) return fc * factor
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 read_fc2_from_hdf5(filename='fc2.hdf5', p2s_map=None): return read_force_constants_hdf5(filename=filename, p2s_map=p2s_map)