pub fn fit_mermin_oscillators(
elf: &OpticalElf,
options: &MerminFitOptions,
) -> Result<MerminFit, ElectronDataError>Expand description
Fit a sum of Mermin oscillators to elf (see the module docs).
§Width floor
Each width ħγ_j is bounded below by the local knot spacing of the table
at ħω_j: the larger of the two gaps next to the tabulated energy nearest
to ħω_j (the single gap of an end knot). The stored parameter ln γ_j
is projected onto the bound (raised to ln of the floor) at the start and
after every accepted step, so a floored width keeps a nonzero Jacobian
column and can move off the floor when the data want it wider. The floor
is also applied inside every residual evaluation (trial and Jacobian
points) and to the reported oscillators, so all three agree. A fit in
which no width ever falls below the floor is unchanged bit for bit; of
the committed ELFs at the default options only C is affected (its start
width 0.05 eV at the 0.2 eV peak is raised to the 0.1 eV knot spacing,
and the fit ends within about 1e-7 of the unbounded one, in 146
iterations instead of 140). The reason: the residuals are evaluated at
the knots only, and a
Lorentzian narrower than the gap it sits in can fall between two knots,
where no residual constrains it while its amplitude, and with it the
f-sum (π/2) A_j, is free (#307: the 10- and 16-oscillator fits of the
committed Cu ELF reached 6771 and 16467 times the table’s f-sum this way).
Such a width is not determined by the tabulated values. This bound is
our own choice: de Vera et al. (2022), section 2.1.1, give no fitting
algorithm, only the Kramers-Kronig and f-sum consistency check, which
MerminFit reports. The floor is a pure function of the knots and adds
no dependence on the thread count.
The floor is a step function of ħω_j: it jumps where the nearest knot
changes, halfway between two knots. For a width at the floor the residual
is therefore discontinuous in ln ħω_j there, and a central difference
straddling the jump gives a large Jacobian entry. The fit accepts only
strict decreases of the cost, so it does not move uphill across a jump,
but it can stop at one: if no damping gives a decrease, it reports
converged = true at a point that is a minimum only on one side of the
jump. Likewise, at a width on the floor where the data want a narrower
line, converged = true means a minimum subject to the bound.
The floor does not bound the f-sum against very wide oscillators: with
10 or 16 oscillators the committed Cu ELF still gets one of width
4e5 to 8e5 eV whose weight lies above the table, where the default
relative weighting barely sees it (f-sum 188 and 106 times the table’s,
unconverged). The weighting does not reliably prevent it (#311; table in
docs/validation.md, “Cu: the Mermin IMFP and the default oscillator
fit”): at 10 oscillators relative floors of 0.1 and 1 avoid it
(f-sum 0.79 and 0.87 of the table’s), FitWeighting::Uniform makes it
worse (4e4 times); at 16 oscillators none of the floors 1e-3 to 1 nor
uniform weighting avoids it, and two of those fits report
converged = true. Every such oscillator found is wider than the table’s
energy range. Check MerminFit::f_sum_ev2 and MerminFit::p_eff
against the table’s whatever the options.