Loading...
Searching...
No Matches
init.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PawPlanewavePseudopotentialKohnShamSCFIterator — SCF with PAW datasets.
5 *
6 * PAW is a layered extension of ultrasoft here, so this extends the ultrasoft
7 * iterator rather than standing beside it. Everything the ultrasoft pathway
8 * does is what PAW needs too — the compensation charge on the grid, the
9 * S-operator from the dataset's q_ij, the projector overlap coefficients — and
10 * three things are added on top:
11 *
12 * 1. **D gets a one-center term.** After the ultrasoft D is built from
13 * ∫v_eff·Q, (D¹ − D̃¹)_Hxc is added per atom, refreshed each step from
14 * the current occupancies.
15 * 2. **The total energy gets Σ_a (E¹_a − Ẽ¹_a),** and the double-counting
16 * correction gets −Σ_a Σ_ij ρ_ij D^oc_ij.
17 * 3. **ρ_ij is symmetrized over the point group** before either of those
18 * reads it. Ultrasoft needs no such step: its only consumer of ρ_ij is
19 * the augmentation charge, which reaches the grid and is repaired there
20 * by the density symmetrizer. The one-centre terms never touch a grid.
21 *
22 * That second subtraction is not optional bookkeeping. The one-center
23 * potential entered the band energy through D, so without removing it the
24 * on-site terms are counted twice — the same correction the grid potential
25 * needs, applied to the on-site part of the same sum. Quantum ESPRESSO
26 * subtracts the identical Σ_ij ρ_ij D^oc_ij inside its own double-counting
27 * function, alongside its −∫v·n. Getting this wrong
28 * produces a converged SCF with a wrong total, which is the failure mode the
29 * A2.6 gate is designed to catch and the reason the two pieces live in
30 * separate energy fields.
31 *
32 * **A non-self-consistent run takes ρ_ij from the checkpoint.** It diagonalizes
33 * once, before it constructs any density, so the one-centre term it would
34 * otherwise use is the empty one the engine starts with: D without it put
35 * copper's 3s at −196.3 eV where the SCF had −92.8. The converged occupations
36 * are restored as soon as the engine is built, and the term stays built from
37 * them for the rest of the run.
38 *
39 * **The projector overlap coefficients are ρ_ij** (Quantum ESPRESSO's
40 * `becsum`). No conversion happens between the array the ultrasoft
41 * iterator accumulates and the occupancy matrix the one-center engine
42 * consumes; they are the same object in the same channel order. That
43 * agreement is a property of the dataset, and `PawOneCenterTerms::build`
44 * refuses datasets where it does not hold rather than computing something
45 * plausible and wrong.
46 */
47
48#include <algorithm>
49#include <limits>
50#include <stdexcept>
51#include <string>
52#include <vector>
53
57
58namespace q3 {
59
62 public:
66
67 [[nodiscard]] std::vector<Matrix<Real>> one_center_occupations() const override {
69 }
70
71 [[nodiscard]] bool requires_one_center_occupations() const override {
72 return true;
73 }
74
75 void
76 load_one_center_occupations(const std::vector<Matrix<Real>>& occupations_by_spin) override {
77 preloaded_one_center_occupations_ = occupations_by_spin;
78 }
79
80 protected:
82
83 /**
84 * The point-group average of ρ_ij, built once from this cell's operations.
85 *
86 * Inactive — and `symmetrize()` a no-op — whenever the density symmetrizer
87 * is, which is the point: `control.disable_symmetry`, a Γ-only basis and a
88 * cell with no operation beyond the identity all stand this down as well,
89 * so the on-site channel and the grid never disagree about whether the run
90 * is imposing symmetry.
91 */
93
94 /**
95 * ρ_ij handed over from a checkpoint, held until the one-centre engine is
96 * built and then kept as what D's one-centre term is built from. Empty for
97 * a self-consistent run, which builds the term from its own occupations.
98 */
99 std::vector<Matrix<Real>> preloaded_one_center_occupations_;
101 std::vector<Matrix<Real>> previous_projector_overlaps_by_spin_;
102
103 /**
104 * ρ_ij^out per spin: the occupancies this iteration's ψ produced,
105 * symmetrized, *before* damping replaces them with the next input. The
106 * energy needs all three arrays -- in, out and mixed -- and damping
107 * overwrites the out array in place, so this is the copy that survives.
108 */
109 std::vector<Matrix<Real>> output_projector_overlaps_by_spin_;
110
111 /**
112 * Σ ρ_ij^out · D^oc(ρ^in): the part of the band energy that D's one-centre
113 * term put there. Band energy is a sum over ψ_out, whose projections are
114 * ρ^out, against the Hamiltonian this iteration was diagonalized with,
115 * whose one-centre D was built from ρ^in -- so this is what the
116 * double-counting term has to remove.
117 */
119
120 /**
121 * −Σ (ρ_ij^mix − ρ_ij^out) · D^oc(ρ^mix): the one-centre half of the SCF
122 * correction, the term that makes the reported energy second order in the
123 * on-site residual. The grid density has always had its half
124 * (`compute_delta_escf_correction`); see `compute_double_counting_correction`
125 * for why the one-centre channel needs one too.
126 */
128
129 /**
130 * ‖ρ_ij^fresh − ρ_ij^damped‖² — how far the occupancies just accumulated
131 * from ψ are from the ones that built D for this iteration, *before* the
132 * damping factor scales the step actually taken. Same squared-magnitude
133 * convention `density_residual_` uses, and the same role
134 * `hubbard_occupation_residual_` plays for DFT+U: it is what tells the SCF
135 * that the on-site channel is still moving.
136 *
137 * Large sentinel until the first real damping step, so it can never make a
138 * run look converged before ρ_ij has been compared against anything.
139 */
140 Real occupancy_residual_{std::numeric_limits<Real>::max()};
141
142 /**
143 * How far ρ_ij is allowed to move per iteration. Chosen to be loose enough
144 * that Si and C converge in the same iteration count they did undamped,
145 * and tight enough to hold the stiff Cu channel.
146 */
147 static constexpr Real occupancy_damping_ = 0.4;
148
154 quantum_system_snapshot_->pseudopotential_basis().pseudopotential_set(),
156 log::info(" PAW: one-center engine active for {} atoms",
157 crystal_structure().number_of_atoms());
158 build_occupation_symmetrizer();
159 }
161 restore_one_center_occupations();
162 }
163
166 /**
167 * A run given the converged occupations keeps the one-centre term built
168 * from them. The ones just accumulated come from this run's own k-points
169 * and occupations -- a band path's, say -- and rebuilding the term from
170 * them would hand the first-iteration re-diagonalization a different D
171 * than the pass it repeats.
172 */
173 /**
174 * D still holds the one-centre term built from ρ^in -- the one the
175 * Hamiltonian just diagonalized used -- so this is the moment to
176 * contract it with ρ^out.
177 */
179 contract_with_one_center_potential(output_projector_overlaps_by_spin_);
181 update_one_center_scf_correction();
182 return;
183 }
184 auto timer_one_center_start = std::chrono::high_resolution_clock::now();
185 refresh_one_center_terms();
186 update_one_center_scf_correction();
187 auto timer_one_center_end = std::chrono::high_resolution_clock::now();
188 log::info(
189 " PAW one-center refresh: {:.1f} ms",
190 std::chrono::duration<double, std::milli>(timer_one_center_end - timer_one_center_start)
191 .count());
192 }
193
194 /**
195 * Damp ρ_ij between iterations, the way QE mixes `rho%bec` alongside the
196 * density.
197 *
198 * Without this the on-site occupancies are recomputed from fresh ψ every
199 * step and fed straight back through D, a loop with gain 1 that the
200 * density mixer cannot damp — lowering the mixing beta does nothing to it,
201 * which is how the problem identifies itself. Whether that matters is a
202 * property of the dataset: Q3 converges Si and C undamped, but the
203 * PseudoDojo Cu PAW dataset has a second p channel carrying an
204 * augmentation charge of 25.2 electrons and D_ion of −71.8 Ry, giving a
205 * one-center D of ~217 Ry, and the loop oscillates between two states
206 * ±212 Ry apart until it is damped.
207 *
208 * Linear damping rather than the full mixer: the fixed point is unchanged
209 * either way, since at self-consistency the new and old occupancies are
210 * equal, so this only sets how fast the loop is allowed to move. Feeding
211 * ρ_ij through the density mixer as QE does would converge stiff cases in
212 * fewer iterations, and is the upgrade if one proves too slow.
213 *
214 * The damped array is what the augmentation charge on the grid sees too,
215 * which is deliberate: the density and the on-site terms have to be built
216 * from the same occupancies or the energy is not a functional of one state.
217 */
220 symmetrize_projector_overlaps();
222 /**
223 * The per-spin arrays are damped by the same factor and in the same
224 * step. Damping them independently, or damping only the total, would
225 * let ρ↑ + ρ↓ drift away from the total the augmentation charge on the
226 * grid was built from, and the energy would stop being a functional of
227 * one state.
228 */
232 for (size_t spin = 0; spin < projector_overlap_coefficients_by_spin_.size(); spin++)
234 std::max(occupancy_residual_,
237 }
238
239 /**
240 * The density residual alone cannot see the on-site channel.
241 *
242 * ρ_ij is a second self-consistent quantity with its own feedback loop,
243 * damped here at a fixed rate rather than driven by the density mixer, and
244 * it converges more slowly than the density and with a period-2
245 * oscillation. Measured on Cu PAW at 80 Ry, the density residual runs two
246 * to four orders of magnitude below ‖δρ_ij‖² near convergence, and the gap
247 * widens as the run proceeds: at dr2 = 1.5e-13 the occupancy residual is
248 * still 6.7e-10. ρ_ij reaches the grid only through the compensation
249 * charge, which is confined to the augmentation sphere and so sits at the
250 * high-|G| end the Hartree metric's 1/|G|² weight suppresses, while the
251 * one-center energy integrates it unweighted. Exiting on dr2
252 * alone therefore stops while E¹ − Ẽ¹ is still moving, and because the
253 * one-center channel has no first-order SCF correction of its own (the
254 * `delta_escf` analogue that makes the grid part second-order in its
255 * error), that residual motion lands in the total energy at first order.
256 * On Cu at 80 Ry that left ~0.6 mRy of scatter in the total energy while
257 * the stress on the same runs moved only ~0.4 kbar, which is why the
258 * defect reads as an energy-only one: the stress is evaluated once from
259 * the final state rather than assembled across iterations, so it carries
260 * no analogous first-order term.
261 *
262 * Same reasoning, same shape as the DFT+U occupation-matrix gate in
263 * `PlanewavePseudopotentialKohnShamSCFIterator::is_iteration_converged()`:
264 * the density can be self-consistent while a potential built from a
265 * still-relaxing occupancy is not.
266 *
267 * `occupancy_residual_` is refreshed in `accumulate_projector_overlaps()`,
268 * which `perform_iteration()` always runs before this is checked, so it is
269 * never stale by an iteration. It is computed from arrays the ultrasoft
270 * accumulation has already pool- and band-reduced, by pure arithmetic with
271 * a rank-invariant damping scalar, so it needs no reduction of its own --
272 * unlike `density_residual_`, whose per-rank FFTW plan noise does.
273 */
278
279 /**
280 * One damping step, in place; seeds `previous` on the first call.
281 *
282 * Returns ‖fresh − damped‖² for that array, or the unconverged sentinel on
283 * the seeding call, where there is no previous array to have moved away
284 * from and zero would be a false "already converged".
285 */
286 [[nodiscard]] Real damp_towards_previous(Matrix<Real>& current_matrix,
287 Matrix<Real>& previous_matrix) const {
288 auto& current = current_matrix.raw();
289 auto& previous = previous_matrix.raw();
290 if (previous.size() != current.size()) {
291 previous_matrix = current_matrix;
292 return std::numeric_limits<Real>::max();
293 }
294 Real residual = 0.0;
295 for (size_t index = 0; index < current.size(); index++) {
296 Real step = current[index] - previous[index];
297 residual += step * step;
298 current[index] = previous[index] + occupancy_damping_ * step;
299 }
300 previous_matrix = current_matrix;
301 return residual;
302 }
303
304 void prepare_hamiltonian() override {
306 /**
307 * The base wired its own D into the quantum system; the one-center
308 * term is added to that same matrix in place, so nothing downstream
309 * needs to know a PAW branch exists.
310 */
311 add_one_center_to_d_matrix();
312 }
313
314 /**
315 * −Σ_a Σ_ij ρ_ij D^oc_ij, on top of the base's −∫ρ·V_Hxc.
316 *
317 * The base's term corrects for the grid potential inside the band energy;
318 * this corrects for the on-site potential that entered it through D. They
319 * are the same correction applied to two different parts of the same sum,
320 * which is why this adds rather than replaces.
321 */
325 /**
326 * Three occupancy arrays are in play by the time the energy is
327 * assembled, and each term has to use the right one:
328 *
329 * ρ^in built the D this iteration's Hamiltonian was diagonalized with
330 * ρ^out the projections of the ψ that came out of it
331 * ρ^mix the damped array the next iteration will start from, which
332 * is also what E¹ and the refreshed D^oc are now built from
333 *
334 * The band energy contains Σ ρ^out · D^oc(ρ^in), so that is what is
335 * removed, and E¹ is evaluated at ρ^mix with the first-order term that
336 * carries it back to ρ^out:
337 *
338 * E¹(ρ^out) ≈ E¹(ρ^mix) − Σ (ρ^mix − ρ^out) · D^oc(ρ^mix)
339 *
340 * which is the one-centre half of the SCF correction and the same
341 * expansion `compute_delta_escf_correction` makes for the grid. With
342 * both, the reported energy is second order in the residual of either
343 * channel. Quantum ESPRESSO's `delta_escf` carries the same PAW term.
344 *
345 * What this used to subtract was Σ ρ^mix · D^oc(ρ^mix), mixed against
346 * refreshed, while the band energy holds out against input. The
347 * difference, Σ ρ^out · (D^oc(ρ^mix) − D^oc(ρ^in)), is first order in
348 * the step the damping takes, and the damping takes a fixed fraction
349 * of the residual -- so the energy carried an error first order in the
350 * on-site residual. On silicon PAW at Γ that kept the energy drifting
351 * by ~3e-9 Ry per iteration after the density residual had reached
352 * 1e-14, and left a run stopped at a 1e-12 threshold 6e-9 Ry from
353 * where it settles.
354 *
355 * At self-consistency the three arrays coincide and this reduces to
356 * the old expression, so a converged energy does not move; what moves
357 * is how close an unconverged one already is.
358 */
360 }
361
366
369 /**
370 * Second rung of the failure ladder. Printed in QE's labels and order
371 * for readability, but see `BranchTotals`: QE's four values are on a
372 * different footing and are not directly differenceable against these.
373 */
374 const auto& branches = one_center_terms_.branch_totals();
375 log::info(" -> PAW hartree energy AE = {:14.9f}", branches.all_electron_hartree);
376 log::info(" -> PAW hartree energy PS = {:14.9f}", branches.pseudo_hartree);
377 log::info(" -> PAW xc energy AE = {:14.9f}", branches.all_electron_xc);
378 log::info(" -> PAW xc energy PS = {:14.9f}", branches.pseudo_xc);
379 }
380
381 private:
382 /**
383 * Put the checkpoint's ρ_ij where the one-centre engine reads it, and build
384 * the term from it now, before the first Hamiltonian is prepared.
385 *
386 * Refused when the arrays do not have this run's shape -- another cell, a
387 * different spin treatment or other datasets -- since reading them anyway
388 * would build D from some other calculation's atoms.
389 */
390 void restore_one_center_occupations() {
391 const auto& preloaded = preloaded_one_center_occupations_;
392 if (preloaded.size() != projector_overlap_coefficients_by_spin_.size())
393 throw std::runtime_error(
394 "PAW: the checkpoint's on-site occupations have " +
395 std::to_string(preloaded.size()) + " spin channel(s), but this run has " +
396 std::to_string(projector_overlap_coefficients_by_spin_.size()) +
397 ". A non-self-consistent run must use the spin treatment of the SCF that wrote "
398 "the checkpoint.");
399 for (size_t spin = 0; spin < preloaded.size(); spin++) {
400 const auto& expected = projector_overlap_coefficients_by_spin_[spin];
401 if (preloaded[spin].rows() != expected.rows() ||
402 preloaded[spin].cols() != expected.cols())
403 throw std::runtime_error(
404 "PAW: the checkpoint's on-site occupations are " +
405 std::to_string(preloaded[spin].rows()) + " by " +
406 std::to_string(preloaded[spin].cols()) + ", but this run's are " +
407 std::to_string(expected.rows()) + " by " + std::to_string(expected.cols()) +
408 ". A non-self-consistent run must use the structure and datasets of the "
409 "SCF that wrote the checkpoint.");
410 }
412 auto& total = projector_overlap_coefficients_.raw();
413 std::fill(total.begin(), total.end(), 0.0);
414 for (const auto& per_spin : preloaded) {
415 const auto& values = per_spin.raw();
416 for (size_t index = 0; index < total.size(); index++)
417 total[index] += values[index];
418 }
419 refresh_one_center_terms();
420 log::info(" PAW: one-center terms built from the checkpoint's on-site occupations");
421 }
422
423 /**
424 * Build the ρ_ij symmetrizer from this cell's operations and datasets.
425 *
426 * Skipped, leaving the symmetrizer inactive, exactly when the density
427 * symmetrizer stood down: `control.disable_symmetry`, a Γ-only basis, or a
428 * cell whose only operation is the identity. Two of those are correctness
429 * conditions rather than optimizations — a Γ-only run's half-sphere basis
430 * breaks the point group by construction, and `disable_symmetry` is the
431 * escape hatch for a cell whose spglib operations are not the ones the user
432 * means — and the third is a no-op either way. Asking the density
433 * symmetrizer rather than re-deriving the conditions keeps the two from
434 * drifting apart, which is what matters: ρ_ij and the grid density are two
435 * halves of one charge density, and symmetrizing one without the other
436 * would make the energy a functional of neither.
437 *
438 * The channel layout comes from the projector mapping table's own
439 * per-channel radial index and l, so the expansion rule lives in one place.
440 */
441 void build_occupation_symmetrizer() {
443 return;
444 const auto& basis = quantum_system_snapshot_->pseudopotential_basis();
445 std::vector<paw_one_center::ChannelAngularLayout> layout_by_species;
446 layout_by_species.reserve(static_cast<size_t>(crystal_structure().number_of_species()));
447 for (int species_index = 0; species_index < crystal_structure().number_of_species();
448 species_index++) {
449 int channels = basis.number_of_projector_channels(species_index);
450 std::vector<int> beta_index(static_cast<size_t>(channels));
451 std::vector<int> angular_momentum(static_cast<size_t>(channels));
452 for (int channel = 0; channel < channels; channel++) {
453 beta_index[static_cast<size_t>(channel)] =
454 basis.projector_to_beta_index(species_index, channel);
455 angular_momentum[static_cast<size_t>(channel)] =
456 basis.projector_angular_momentum(species_index, channel);
457 }
458 layout_by_species.push_back(
459 paw_one_center::build_channel_angular_layout(beta_index, angular_momentum));
460 }
462 crystal_structure(), cached_symmetry_operations(), std::move(layout_by_species));
464 log::info(" PAW: on-site occupations symmetrized over {} symmetry operations",
466 }
467
468 /**
469 * Restore to ρ_ij the symmetry the irreducible-wedge sum does not carry.
470 *
471 * Before the damping step, so that what is compared against the previous
472 * iteration — and what `occupancy_residual_` measures — is the quantity the
473 * one-centre term is actually built from. Damping a symmetrized array
474 * towards a symmetrized one keeps it symmetric, a convex combination being
475 * an average of averages.
476 *
477 * Every array, per-spin and total together: they are the same numbers
478 * summed differently, and symmetrization is linear, so averaging them
479 * apart cannot make them disagree.
480 *
481 * Needs no reduction of its own, for the reason the damping step below
482 * does not: the base has already pool- and band-reduced these arrays, so
483 * every rank runs the same arithmetic on the same values and lands on the
484 * same answer.
485 *
486 * Not on a run reading ρ_ij from a checkpoint. There the occupations that
487 * matter came from an SCF that already symmetrized them, and this pass's
488 * own k-points are a band path — an arbitrary set, not a mesh closed under
489 * the point group — so averaging what it accumulates over the group would
490 * assert a symmetry the sampling does not have.
491 */
492 void symmetrize_projector_overlaps() {
494 return;
496 for (auto& per_spin : projector_overlap_coefficients_by_spin_)
497 occupation_symmetrizer_.symmetrize(crystal_structure(), per_spin);
498 }
499
500 /// Recompute the one-center energy and D from the occupancies just accumulated.
501 void refresh_one_center_terms() {
503 return;
504 std::vector<const Matrix<Real>*> coefficient_pointers_by_spin;
505 coefficient_pointers_by_spin.reserve(projector_overlap_coefficients_by_spin_.size());
506 for (const auto& per_spin : projector_overlap_coefficients_by_spin_)
507 coefficient_pointers_by_spin.push_back(&per_spin);
509 crystal_structure(), coefficient_pointers_by_spin, projector_overlap_row_capacity());
510 }
511
512 void add_one_center_to_d_matrix() {
514 return;
515 int number_of_atoms = crystal_structure().number_of_atoms();
516 /**
517 * Added to every spin channel's D, not the spin-free matrix: the base
518 * built one D per channel, and `element()` reads those, so a correction
519 * written only to the shared matrix would be dropped.
520 */
521 for (int spin = 0; spin < number_of_spin_components(); spin++) {
522 std::vector<std::vector<Real>> corrections(number_of_atoms);
523 for (int atom_index = 0; atom_index < number_of_atoms; atom_index++)
524 corrections[atom_index] = one_center_terms_.d_correction(atom_index, spin);
526 }
527 }
528
529 /// Σ_a Σ_ij ρ_ij D^oc_ij, over the same channel indexing ρ_ij uses.
530 /**
531 * −Σ (ρ^mix − ρ^out) · D^oc(ρ^mix), with D^oc as it now stands.
532 *
533 * Called after the refresh (or, for a run reading ρ_ij from a checkpoint,
534 * in place of it, where D^oc never moved and ρ^mix is what was preloaded).
535 */
536 void update_one_center_scf_correction() {
538 contract_with_one_center_potential(output_projector_overlaps_by_spin_) -
539 contract_with_one_center_potential(projector_overlap_coefficients_by_spin_);
540 }
541
542 [[nodiscard]] Real contract_with_one_center_potential(
543 const std::vector<Matrix<Real>>& coefficients_by_spin) const {
545 return 0.0;
546 Real accumulated = 0.0;
547 /**
548 * Σ_σ Σ_a Σ_ij ρ^σ_ij D^oc,σ_ij — each channel's occupancies against its
549 * own D. Pairing the spin-summed ρ_ij with one channel's D would
550 * double count one channel and drop the other.
551 *
552 * Indexed by the atom's own channel count, which is the stride ρ_ij
553 * is written with; see the note in `PawOneCenterTerms::update_by_spin`.
554 */
555 for (size_t spin = 0; spin < coefficients_by_spin.size(); spin++) {
556 const auto& coefficients_for_spin = coefficients_by_spin[spin];
557 for (int atom_index = 0; atom_index < crystal_structure().number_of_atoms();
558 atom_index++) {
559 const auto& correction =
560 one_center_terms_.d_correction(atom_index, static_cast<int>(spin));
561 if (correction.empty())
562 continue;
563 int species_index = crystal_structure().species_type_index(atom_index);
564 int number_of_channels = one_center_terms_.number_of_channels(species_index);
565 for (int first = 0; first < number_of_channels; first++) {
566 for (int second = 0; second < number_of_channels; second++) {
567 accumulated +=
568 coefficients_for_spin[atom_index][first * number_of_channels + second] *
569 correction[first * number_of_channels + second];
570 }
571 }
572 }
573 }
574 return accumulated;
575 }
576
577 /**
578 * Allocated row length of the projector overlap array.
579 *
580 * The ultrasoft iterator sizes ρ_ij rows by the *maximum* channel count
581 * over species so a mixed cell's array is rectangular. It is **not** the
582 * indexing stride: the accumulation writes at `i * nh_atom + j`. Passed
583 * down only so the reader can bound-check itself.
584 */
585 [[nodiscard]] int projector_overlap_row_capacity() const {
586 int maximum_channels = 0;
587 const auto& basis = quantum_system_snapshot_->pseudopotential_basis();
588 for (int species_index = 0; species_index < crystal_structure().number_of_species();
589 species_index++)
590 maximum_channels =
591 std::max(maximum_channels, basis.number_of_projector_channels(species_index));
592 return maximum_channels;
593 }
594};
595
596} // namespace q3
int number_of_species() const
Definition crystal.hpp:212
int species_type_index(int atom_index) const
Definition crystal.hpp:273
int number_of_atoms() const
Definition crystal.hpp:209
const KohnShamSCFIteratorConfig & config() const
Definition init.hpp:256
virtual void report_convergence_details()=0
Crystal & crystal_structure() const
Definition init.hpp:219
virtual Real compute_double_counting_correction() const =0
virtual void compute_energy_components()
Definition init.hpp:622
const XCFunctional & exchange_correlation() const
Definition init.hpp:190
std::vector< T > & raw()
Returns raw vector (useful for MPI calls that need contiguous block)
Definition matrix.hpp:83
void load_one_center_occupations(const std::vector< Matrix< Real > > &occupations_by_spin) override
Definition init.hpp:76
Real damp_towards_previous(Matrix< Real > &current_matrix, Matrix< Real > &previous_matrix) const
Definition init.hpp:286
Real compute_double_counting_correction() const override
Definition init.hpp:322
std::vector< Matrix< Real > > output_projector_overlaps_by_spin_
Definition init.hpp:109
std::vector< Matrix< Real > > one_center_occupations() const override
Definition init.hpp:67
std::vector< Matrix< Real > > previous_projector_overlaps_by_spin_
Definition init.hpp:101
std::vector< Matrix< Real > > preloaded_one_center_occupations_
Definition init.hpp:99
~PawPlanewavePseudopotentialKohnShamSCFIterator() override=default
bool requires_one_center_occupations() const override
Definition init.hpp:71
PawPlanewavePseudopotentialKohnShamSCFIterator(KohnShamSCFIteratorConfig config)
Definition init.hpp:63
paw_one_center::PawOneCenterTerms one_center_terms_
Definition init.hpp:81
paw_one_center::OnSiteOccupationSymmetrizer occupation_symmetrizer_
Definition init.hpp:92
PlanewaveChargeDensitySymmetrizer density_symmetrizer_
Definition init.hpp:397
std::shared_ptr< NormConservingPlanewaveKohnShamQuantumSystem > quantum_system_snapshot_
Definition init.hpp:372
NormConservingPlanewaveKohnShamEnergies energies_
Definition init.hpp:371
const std::vector< SymmetryOperation > & cached_symmetry_operations() const
Definition init.hpp:430
Real convergence_threshold_
Definition init.hpp:104
virtual bool is_iteration_converged() const =0
int number_of_spin_components() const
Definition init.hpp:45
void add_per_atom_d_terms_for_spin(int spin, const std::vector< std::vector< Real > > &terms)
Definition init.hpp:88
std::vector< Matrix< Real > > projector_overlap_coefficients_by_spin_
Definition init.hpp:69
UltrasoftPlanewaveEffectivePotential nonlocal_effective_potential_
Definition init.hpp:70
void symmetrize(const Crystal &crystal_structure, Matrix< Real > &occupations) const
void build(const Crystal &crystal_structure, const std::vector< SymmetryOperation > &symmetry_operations, std::vector< ChannelAngularLayout > layout_by_species)
const std::vector< Real > & d_correction(int atom_index, int spin=0) const
const BranchTotals & branch_totals() const
int number_of_channels(int species_index) const
Real energy() const
Σ_a (E¹_a − Ẽ¹_a), in Rydberg.
void build(const Crystal &crystal_structure, const PseudopotentialSet &pseudopotential_set, const XCFunctional &functional, int angular_order=0)
void update_by_spin(const Crystal &crystal_structure, const std::vector< const Matrix< Real > * > &projector_overlap_coefficients_by_spin, int row_capacity)
void info(spdlog::format_string_t< Args... > fmt, Args &&... args)
Definition logger.hpp:183
ChannelAngularLayout build_channel_angular_layout(const std::vector< int > &beta_index_per_channel, const std::vector< int > &angular_momentum_per_channel)
double Real