87 void Apply(Eigen::VectorXd& energies,
const Eigen::VectorXd& dft,
90 const Index lumo = homo + 1;
92 ShiftSide(energies, dft, rpamin, rpamin, qpmin - 1, qpmin,
93 std::min(homo, qpmax),
true);
96 ShiftSide(energies, dft, rpamin, qpmax + 1, rpamax, std::max(lumo, qpmin),
106 void ShiftSide(Eigen::VectorXd& energies,
const Eigen::VectorXd& dft,
108 Index win_last,
bool below)
const {
109 const Index nwin = win_last - win_first + 1;
110 auto correction = [&](
Index level) {
111 return energies(level - rpamin) - dft(level);
113 auto out = energies.segment(out_first - rpamin, out_last - out_first + 1);
118 double max_correction = 0.0;
119 for (
Index l = win_first; l <= win_last; ++l) {
120 max_correction = std::max(max_correction, std::abs(correction(l)));
122 out.array() += below ? -max_correction : max_correction;
125 const Index boundary = below ? win_first : win_last;
133 out.array() += correction(boundary);
138 const Index fit_first = below ? win_first : win_last - nfit + 1;
139 const double e_b = dft(boundary);
140 double sx = 0, sy = 0, sxx = 0, sxy = 0, span = 0;
141 for (
Index l = fit_first; l < fit_first + nfit; ++l) {
142 const double x = dft(l) - e_b;
143 const double y = correction(l);
148 span = std::max(span, std::abs(x));
150 const double n = double(nfit);
151 const double var = sxx - sx * sx / n;
152 const double b = (var > 1
e-12 * n) ? (sxy - sx * sy / n) / var : 0.0;
153 const double a = (sy - b * sx) / n;
154 for (
Index l = out_first; l <= out_last; ++l) {
155 const double x = std::clamp(dft(l) - e_b, -span, span);
156 energies(l - rpamin) += a + b * x;