def _bands_from_force_constants(data: ForceConstants, q_distance: Quantity, insert_gamma: bool = True, frequencies_only: bool = False, **calc_modes_kwargs ) -> Tuple[Union[QpointPhononModes, QpointFrequencies], XTickLabels, SplitArgs]: structure = data.crystal.to_spglib_cell() bandpath = seekpath.get_explicit_k_path( structure, reference_distance=q_distance.to('1 / angstrom').magnitude) if insert_gamma: _insert_gamma(bandpath) x_tick_labels = _get_tick_labels(bandpath) split_args = {'indices': _get_break_points(bandpath)} print( "Computing phonon modes: {n_modes} modes across {n_qpts} q-points" .format(n_modes=(data.crystal.n_atoms * 3), n_qpts=len(bandpath["explicit_kpoints_rel"]))) qpts = bandpath["explicit_kpoints_rel"] if frequencies_only: modes = data.calculate_qpoint_frequencies(qpts, reduce_qpts=False, **calc_modes_kwargs) else: modes = data.calculate_qpoint_phonon_modes(qpts, reduce_qpts=False, **calc_modes_kwargs) return modes, x_tick_labels, split_args
def _get_debye_waller(temperature: Quantity, fc: ForceConstants, grid: Optional[Sequence[int]] = None, grid_spacing: Quantity = 0.1 * ureg('1/angstrom'), **calc_modes_kwargs ) -> DebyeWaller: """Generate Debye-Waller data from force constants and grid specification """ mp_grid_spec = _grid_spec_from_args(fc.crystal, grid=grid, grid_spacing=grid_spacing) print("Calculating Debye-Waller factor on {} q-point grid" .format(' x '.join(map(str, mp_grid_spec)))) dw_phonons = fc.calculate_qpoint_phonon_modes( euphonic.util.mp_grid(mp_grid_spec), **calc_modes_kwargs) return dw_phonons.calculate_debye_waller(temperature)
def sample_sphere_structure_factor( fc: ForceConstants, mod_q: Quantity, dw: DebyeWaller = None, dw_spacing: Quantity = 0.025 * ureg('1/angstrom'), temperature: Optional[Quantity] = 273. * ureg['K'], sampling: str = 'golden', npts: int = 1000, jitter: bool = False, energy_bins: Quantity = None, scattering_lengths: Union[dict, str] = 'Sears1992', **calc_modes_args ) -> Spectrum1D: """Sample structure factor, averaging over a sphere of constant |q| (Specifically, this is the one-phonon inelastic-scattering structure factor as implemented in QpointPhononModes.calculate_structure_factor().) Parameters ---------- fc Force constant data for system mod_q scalar radius of sphere from which vector q samples are taken dw Debye-Waller exponent used for evaluation of scattering function. If not provided, this is generated automatically over Monkhorst-Pack q-point mesh determined by ``dw_spacing``. dw_spacing Maximum distance between q-points in automatic q-point mesh (if used) for Debye-Waller calculation. temperature Temperature for Debye-Waller calculation. If both temperature and dw are set to None, Debye-Waller factor will be omitted. sampling Sphere-sampling scheme. (Case-insensitive) options are: - 'golden': Fibonnaci-like sampling that steps regularly along one spherical coordinate while making irrational steps in the other - 'sphere-projected-grid': Regular 2-D square mesh projected onto sphere. npts will be distributed as evenly as possible (i.e. using twice as many 'longitude' as 'lattitude' lines), rounding up if necessary. - 'spherical-polar-grid': Mesh over regular subdivisions in spherical polar coordinates. npts will be rounded up as necessary in the same scheme as for sphere-projected-grid. 'Latitude' lines are evenly-spaced in z - 'spherical-polar-improved': npts distributed as regularly as possible using spherical polar coordinates: 'latitude' lines are evenly-spaced in z and points are distributed among these rings to obtain most even spacing possible. - 'random-sphere': Points are distributed randomly in unit square and projected onto sphere. npts Number of samples. Note that some sampling methods have constraints on valid values and will round up as appropriate. jitter For non-random sampling schemes, apply an additional random displacement to each point. energy_bins Preferred energy bin edges. If not provided, will setup 1000 bins (1001 bin edges) from 0 to 1.05 * [max energy] scattering_lengths Dict of neutron scattering lengths labelled by element. If a string is provided, this selects coherent scattering lengths from reference data by setting the 'label' argument of the euphonic.util.get_reference_data() function. **calc_modes_args other keyword arguments (e.g. 'use_c') will be passed to ForceConstants.calculate_qpoint_phonon_modes() Returns ------- Spectrum1D """ if isinstance(scattering_lengths, str): scattering_lengths = get_reference_data( physical_property='coherent_scattering_length', collection=scattering_lengths) # type: dict if temperature is not None: if (dw is None): dw_qpts = mp_grid(fc.crystal.get_mp_grid_spec(dw_spacing)) dw_phonons = fc.calculate_qpoint_phonon_modes(dw_qpts, **calc_modes_args) dw = dw_phonons.calculate_debye_waller(temperature ) # type: DebyeWaller else: if not np.isclose(dw.temperature.to('K').magnitude, temperature.to('K').magnitude): raise ValueError('Temperature argument is not consistent with ' 'temperature stored in DebyeWaller object.') qpts_cart = _get_qpts_sphere(npts, sampling=sampling, jitter=jitter ) * mod_q qpts_frac = _qpts_cart_to_frac(qpts_cart, fc.crystal) phonons = fc.calculate_qpoint_phonon_modes(qpts_frac, **calc_modes_args ) # type: QpointPhononModes if energy_bins is None: energy_bins = _get_default_bins(phonons) s = phonons.calculate_structure_factor( scattering_lengths=scattering_lengths, dw=dw) return s.calculate_1d_average(energy_bins)