48 : settings_(settings), classifier_(settings.thresholds) {}
51 require_supported(inputs);
58 const std::vector<DenseMatrix<Complex>> projections =
85 "ProjectabilityDisentanglementSelection: disentanglement needs the neighbour "
86 "overlaps M_mn(k,b), and this record carries none. A record imported from another "
87 "code's projections and eigenvalues alone cannot be disentangled; recapture it "
91 throw WannierDiagnosticError(
93 "ProjectabilityDisentanglementSelection: disentanglement classifies bands by "
94 "their projectability p_nk = sum_m |A_mn(k)|^2, and this record carries none. "
95 "Like the overlaps above this is a capability the record lacks rather than a "
96 "value to choose; recapture it with Q3.");
101 static void log_classification(
const BandClassificationSummary& summary) {
102 log::info(
"disentanglement: {} ({} band{} crossing the Fermi level); frozen window "
104 summary.metallic ?
"a metal" :
"an insulator",
105 summary.number_of_bands_crossing_fermi,
106 summary.number_of_bands_crossing_fermi == 1 ?
"" :
"s",
107 summary.frozen_window_above_fermi_rydberg * constants::
RY_TO_EV,
108 summary.frozen_window_automatic ?
" chosen automatically" :
" as given");
109 for (
const BandExcludedFromFreeze& band : summary.bands_excluded_from_freeze) {
110 log::warn(
"disentanglement: band {} lies inside the frozen window at {} k-point{} "
111 "where its projectability is below the minimum, so it was excluded from "
112 "the freeze there rather than frozen -- the trial orbitals cannot "
113 "represent it, and freezing it would make the gauge singular. The model "
114 "has no state of that character at those k-points.",
116 band.number_of_kpoints,
117 band.number_of_kpoints == 1 ?
"" :
"s");
122 [[nodiscard]]
static std::vector<DenseMatrix<Complex>>
123 frames_of(
const std::vector<DenseMatrix<Complex>>& chosen_subspaces,
124 const std::vector<DenseMatrix<Complex>>& projections,
125 const BandClassification& classification,
126 const WannierInputs& record) {
127 std::vector<DenseMatrix<Complex>> frames;
128 frames.reserve(chosen_subspaces.size());
129 for (std::size_t kpoint_index = 0; kpoint_index < chosen_subspaces.size(); kpoint_index++) {
130 const DenseMatrix<Complex>& chosen = chosen_subspaces[kpoint_index];
134 projections[kpoint_index]);
138 gauge_inside(reduced,
139 static_cast<int>(kpoint_index),
140 classification.kpoints[kpoint_index],
158 [[nodiscard]]
static DenseMatrix<Complex> gauge_inside(
const DenseMatrix<Complex>& reduced,
160 const KPointBandClassification& entry,
161 const WannierInputs& record) {
163 return ProjectionGauge().compute(reduced);
164 }
catch (
const WannierDiagnosticError& error) {
165 throw WannierDiagnosticError(
167 std::string(
error.what()) +
" This is k-point " + std::to_string(kpoint_index) +
168 " of the disentangled window, where " + std::to_string(entry.number_frozen()) +
169 " of " + std::to_string(entry.number_kept()) +
" kept bands are frozen" +
170 likely_cause(kpoint_index, entry, record));
180 [[nodiscard]]
static std::string likely_cause(
int kpoint_index,
181 const KPointBandClassification& entry,
182 const WannierInputs& record) {
183 if (entry.frozen_positions.empty()) {
184 return ". No band is frozen there, so the energy rule is not the cause: the subspace "
185 "the iteration chose holds a direction the trial orbitals cannot reach. Raise "
186 "control.interpolation.projectability_minimum so bands they cannot represent "
187 "are not kept, or give the trial orbitals a shell that can represent them.";
189 const std::vector<Real>& projectabilities =
190 record.projectabilities[
static_cast<std::size_t
>(kpoint_index)];
191 int weakest_band = entry.kept_bands[
static_cast<std::size_t
>(entry.frozen_positions[0])];
192 for (
const int position : entry.frozen_positions) {
193 const int band = entry.kept_bands[
static_cast<std::size_t
>(position)];
194 if (projectabilities[
static_cast<std::size_t
>(band)] <
195 projectabilities[
static_cast<std::size_t
>(weakest_band)]) {
199 return " and the least projectable of them is band " + std::to_string(weakest_band + 1) +
201 std::to_string(projectabilities[
static_cast<std::size_t
>(weakest_band)]) +
202 ". A frozen band with no projectability is a direction the trial orbitals cannot "
203 "reach, and it is the usual cause: lower "
204 "control.interpolation.frozen_window_above_fermi_ev so the energy rule stops "
205 "claiming it, or give the trial orbitals a shell that can represent it.";
208 ProjectabilityDisentanglementSettings settings_;
209 BandClassifier classifier_;
DenseMatrix< Complex > multiply(MatrixOperation left_operation, const DenseMatrix< Complex > &left, MatrixOperation right_operation, const DenseMatrix< Complex > &right, Complex alpha=Complex(1.0, 0.0))
alpha * op(left) * op(right), as a new matrix of the product's shape.