Skip to main content

fit_mermin_oscillators

Function fit_mermin_oscillators 

Source
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.