pub struct DiimfpGrid { /* private fields */ }Expand description
The full Penn DIIMFP of one table build, tabulated so that each row of the table costs interpolations instead of nested integrals (issue #256).
The DIIMFP is p(T, ω) = (1/(π T')) ∫_{q-}^{q+} Im[-1/ε(q, ω)] dq/q
(S2017 eq. (2)), and only the window [q-, q+] depends on T. So for a
set of loss nodes ω_i the grid stores the integrand Im[-1/ε(q, ω_i)]
as a function of u = ln q, once, over every window it can be asked for
(from a quarter of q- at the highest table energy to 2k there): the
accepted panels of an adaptive Gauss-Legendre integration
(quadrature::integrate_panels) from segments 0.125 wide in u, at a
tenth of the model tolerance and with every segment held to that
tolerance relative to its own integral (down to 1e-4 of the mean
segment), so that a narrow window is as accurate as a wide one. The
integral to any u comes from the polynomial through the node values of
its panel (quadrature::Panels), so the integral over the window of any
(T, ω_i) costs no new evaluation. (With 0.5-wide starting segments and
the mean-segment floor of FullPenn::diimfp_per_m_ev, the bisection
was seen to stop early, by coincidence, at a few isolated ω near the Al
plasmon, with window errors up to 1.5e-3; the finer segments removed
these.)
Between two loss nodes the window integrals of the two neighbouring
profiles, each over the window of the requested (T, ω), are
interpolated linearly in ln p against ln ω (exact for a power law,
the shape of the DIIMFP’s tails; linear in p where one of them is
zero). The nodes are the two ends ω = ω_min (FULL_LOWEST_LOSS_FRACTION
of the lowest table energy, or the lowest ELF energy if lower; #361) and
ω = T_max, the lowest ELF energy, every ELF knot in between (where Im[-1/ε] has kinks at
small q, and where a feature narrower than the knot spacing sits) and a
subdivision to cells no wider than 0.25 in ln ω. A cell is then
halved, level by level, while at its midpoint ω_m, for any row energy
T > ω_m of the table,
|ω_m (p_exact - p_interp)| > tol · max(ω_m p_exact, ḡ_T), with tol
the model tolerance and ḡ_T the mean of ω p(T, ω) over ln ω on the
current nodes (the row’s average loss density in ln ω, the scale of
the table’s own density tolerance). The interpolation error is therefore
held to the model tolerance (relative, or relative to the row’s average
density where the DIIMFP is below it) at the midpoints checked, with the
row energies of the table as the test set. Every computed midpoint is
kept as a node. Cells are not halved below 1e-4 in ln ω, nor beyond
20000 nodes; a cell that still fails there is counted in
Self::unresolved_cells and kept, and Self::diimfp_per_m_ev
does not answer inside it (the caller uses the direct model there), so
no unchecked interpolation enters a table.
Implementations§
Source§impl DiimfpGrid
impl DiimfpGrid
Sourcepub fn panel_count(&self) -> usize
pub fn panel_count(&self) -> usize
Total number of momentum panels over all profiles.
Sourcepub fn unconverged_profile_panels(&self) -> u64
pub fn unconverged_profile_panels(&self) -> u64
Number of cells of the momentum integrations of the profiles that were accepted without meeting their tolerance (budget of the bisection spent, maximum depth, or a midpoint that is not representable; #298). Zero when every profile converged.
Sourcepub fn unconverged_profile_loss_evaluations(&self) -> u64
pub fn unconverged_profile_loss_evaluations(&self) -> u64
Number of evaluations of the loss function inside the profiles whose
own ω_p integral did not converge (see
FullPenn::loss_function_evaluation). Zero when every evaluation
converged.
Sourcepub fn largest_unconverged_profile_error(&self) -> f64
pub fn largest_unconverged_profile_error(&self) -> f64
The largest error estimate of the cells counted in
Self::unconverged_profile_panels within one profile, relative to
that profile’s integral over its whole momentum range (zero when
every profile converged).
Sourcepub fn unresolved_cells(&self) -> usize
pub fn unresolved_cells(&self) -> usize
Number of cells that failed the interpolation check but were not halved, at the narrowest cell width or the node cap (zero when the refinement converged).
Sourcepub fn loss_is_unresolved_ev(&self, loss_ev: f64) -> bool
pub fn loss_is_unresolved_ev(&self, loss_ev: f64) -> bool
Whether loss loss_ev (eV) lies in an unresolved cell, where
Self::diimfp_per_m_ev gives no answer.
Sourcepub fn unresolved_loss_range_ev(&self) -> Option<(f64, f64)>
pub fn unresolved_loss_range_ev(&self) -> Option<(f64, f64)>
The loss range, eV, from the lowest to the highest edge of the
cells counted in Self::unresolved_cells; None when there are
none. The grid answers in none of these cells.
Sourcepub fn diimfp_per_m_ev(&self, energy_ev: f64, loss_ev: f64) -> Option<f64>
pub fn diimfp_per_m_ev(&self, energy_ev: f64, loss_ev: f64) -> Option<f64>
The DIIMFP at kinetic energy energy_ev (above the Fermi level) and
loss loss_ev, m⁻¹ eV⁻¹, from the grid; None where the grid does
not cover it (a loss below the lowest node, FULL_LOWEST_LOSS_FRACTION of
the lowest table energy, an energy above
the highest table energy, or a loss in an unresolved cell, see
Self::unresolved_cells), where the caller uses
FullPenn::diimfp_per_m_ev. Zero for ω <= 0 or ω > T, as there.
Any T up to the highest table energy is answered, but the
refinement of the loss nodes checks the interpolation only at the
energies passed to FullPenn::diimfp_grid. The accuracy is
controlled at those energies; between them it is not checked.
Trait Implementations§
Source§impl Clone for DiimfpGrid
impl Clone for DiimfpGrid
Source§fn clone(&self) -> DiimfpGrid
fn clone(&self) -> DiimfpGrid
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for DiimfpGrid
impl RefUnwindSafe for DiimfpGrid
impl Send for DiimfpGrid
impl Sync for DiimfpGrid
impl Unpin for DiimfpGrid
impl UnsafeUnpin for DiimfpGrid
impl UnwindSafe for DiimfpGrid
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more