26#include <system_error>
27#include <unordered_map>
135 const std::string& prefix)
const override {
138 log::warn(
"Checkpoint output is not supported when ranks share a k-point pool: "
139 "they split each k-point's plane-wave coefficients and the density "
140 "grid between them, and the checkpoint writers have no gather for "
141 "either. No checkpoint directory was created; results output is "
142 "unaffected. Give every rank its own pool, as the automatic MPI "
143 "topology does, to write one.");
147 auto scf_state =
result();
149 std::string save_directory = output_directory +
"/" + prefix +
".save";
155 std::error_code directory_error;
156 std::filesystem::create_directories(save_directory, directory_error);
157 if (!std::filesystem::is_directory(save_directory)) {
158 throw std::runtime_error(
"Cannot create the checkpoint directory '" + save_directory +
159 "': " + directory_error.message());
163 wavefunctions_checkpoint->write_to_file(save_directory);
169 log::info(
" Each of the {} k-point pools wrote the wavefunctions of its own "
170 "k-points, {} in all",
176 charge_density_checkpoint->write_to_file(save_directory +
"/charge-density.dat");
194 static_cast<int>(eigenvalues_of_every_kpoint.
rows());
196 static_cast<int>(eigenvalues_of_every_kpoint.
cols());
199 effective_potential_snapshot.
eigenvalues = eigenvalues_of_every_kpoint;
205 effective_potential_checkpoint.
save(save_directory +
"/effective-potential.q3cp",
206 effective_potential_snapshot,
291 [[maybe_unused]]
const std::vector<
Matrix<Real>>& occupations_by_spin) {}
341 return valence_calculator
357 starting_wavefunction_directory_ = std::move(save_directory);
379 std::optional<PseudopotentialSet> owned_pseudopotential_set_;
381 bool dispersion_energy_computed_ =
false;
383 std::unique_ptr<NormConservingPlanewaveEffectivePotentialCalculator>
384 effective_potential_calculator_;
386 std::string starting_wavefunction_directory_;
397 for (
int kpoint_index = 0;
483 bool any_nonzero_magnetization =
false;
484 for (
const auto* magnetizations :
487 if (magnetization < -1.0 || magnetization > 1.0)
488 throw std::runtime_error(
489 "starting_magnetization values must be in [-1, 1], got " +
492 any_nonzero_magnetization =
true;
502 config().smearing ==
"none") {
503 log::warn(
"LSDA with fixed occupations pins the total moment to zero; the "
504 "requested starting_magnetization can only seed a local (e.g. AFM) "
505 "spin arrangement. Use smearing to allow a net moment.");
519 log::info(
" The saved starting density does not fit this run's grid; "
520 "starting from overlapping atoms instead");
545 if (
config().hubbard.empty()) {
549 throw std::runtime_error(
550 "DFT+U (hubbard) requires diagonalization: davidson (the direct diagonalizer "
551 "does not go through the Hamiltonian applicator this feature hooks into)");
553 if (
config().hubbard_projector_type !=
"atomic" &&
554 config().hubbard_projector_type !=
"ortho-atomic") {
555 throw std::runtime_error(
"DFT+U: unrecognized hubbard_projector_type '" +
556 config().hubbard_projector_type +
557 "' (expected 'atomic' or 'ortho-atomic')");
575 throw std::runtime_error(
576 "hubbard starting eigenvalue for species '" + directive.species_symbol +
577 "' addresses spin channel " + std::to_string(directive.spin_index + 1) +
579 " spin component(s)");
580 bool species_has_manifold =
584 return crystal_structure().element(manifold.atom_index) ==
585 directive.species_symbol;
587 if (!species_has_manifold)
588 throw std::runtime_error(
"hubbard starting eigenvalue names species '" +
589 directive.species_symbol +
590 "', which has no Hubbard manifold");
595 : 1 + std::max(0,
config().hubbard_fixed_occupation_iterations);
608 constexpr Real q_spacing = 0.01;
609 constexpr int number_of_q_points = 900;
618 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; ++kpoint_index) {
619 std::vector<std::vector<Complex>> all_atomic_orbitals;
628 atomic_wavefunction_table,
631 all_atomic_orbitals);
634 int number_of_atomic_orbitals =
static_cast<int>(all_atomic_orbitals.size());
635 std::unique_ptr<OverlapOperator> overlap_operator;
638 const auto& pseudopotential_basis =
644 pseudopotential_basis.pseudopotential_set(),
645 pseudopotential_basis.beta_function_table(),
647 plane_waves_at_kpoint,
648 pseudopotential_basis.total_number_of_projectors(),
649 kleinman_bylander_projectors);
652 kleinman_bylander_projectors,
664 if (
config().hubbard_projector_type ==
"ortho-atomic") {
665 std::vector<Complex> packed_atomic_orbitals(
666 static_cast<size_t>(plane_waves_at_kpoint) * number_of_atomic_orbitals);
667 for (
int orbital_index = 0; orbital_index < number_of_atomic_orbitals;
669 std::copy(all_atomic_orbitals[
static_cast<size_t>(orbital_index)].begin(),
670 all_atomic_orbitals[
static_cast<size_t>(orbital_index)].end(),
671 packed_atomic_orbitals.begin() +
672 static_cast<size_t>(orbital_index) * plane_waves_at_kpoint);
681 std::vector<Complex> overlap_applied_atomic_orbitals;
682 const Complex* metric_right_orbitals = packed_atomic_orbitals.data();
683 if (overlap_operator !=
nullptr) {
684 overlap_applied_atomic_orbitals.resize(packed_atomic_orbitals.size());
685 overlap_operator->apply_batch(plane_waves_at_kpoint,
686 number_of_atomic_orbitals,
687 packed_atomic_orbitals.data(),
688 overlap_applied_atomic_orbitals.data());
689 metric_right_orbitals = overlap_applied_atomic_orbitals.data();
692 std::vector<Complex> atomic_orbital_overlap;
694 number_of_atomic_orbitals,
695 number_of_atomic_orbitals,
696 packed_atomic_orbitals.data(),
697 metric_right_orbitals,
698 atomic_orbital_overlap);
708 plane_waves_at_kpoint,
709 number_of_atomic_orbitals,
710 number_of_atomic_orbitals,
711 packed_atomic_orbitals.data(),
712 metric_right_orbitals,
715 plane_waves_at_kpoint),
717 atomic_orbital_overlap);
720 atomic_orbital_overlap.data(),
static_cast<int>(atomic_orbital_overlap.size()));
722 std::move(atomic_orbital_overlap));
729 for (
int orbital_index : manifold.orbital_indices) {
733 all_atomic_orbitals[
static_cast<size_t>(orbital_index)]
734 [
static_cast<size_t>(g_index)];
752 if (overlap_operator !=
nullptr) {
753 std::vector<Complex> overlap_applied_hubbard_projectors(
755 overlap_operator->apply_batch(plane_waves_at_kpoint,
758 overlap_applied_hubbard_projectors.data());
759 std::copy(overlap_applied_hubbard_projectors.begin(),
760 overlap_applied_hubbard_projectors.end(),
768 log::info(
" DFT+U (Hubbard): {} manifold(s), {} total orbital(s), {} projectors",
771 config().hubbard_projector_type);
781 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; ++kpoint_index) {
798 auto timer_0 = std::chrono::high_resolution_clock::now();
809 auto timer_1 = std::chrono::high_resolution_clock::now();
812 auto timer_2 = std::chrono::high_resolution_clock::now();
819 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; ++kpoint_index) {
834 auto timer_3 = std::chrono::high_resolution_clock::now();
849 std::vector<std::vector<Real>> starting_guess_potential(
855 total_smooth_points);
856 auto& potential = starting_guess_potential[
static_cast<std::size_t
>(spin_index)];
858 Real inverse_smooth_points = 1.0 / total_smooth_points;
859 for (
auto& value : potential) {
860 value *= inverse_smooth_points;
872 const bool reuse_saved_wavefunctions =
874 if (!starting_wavefunction_directory_.empty() && !reuse_saved_wavefunctions) {
875 log::info(
" Saved bands at '{}' not reused: the checkpoint holds one spin "
876 "channel and this run has {}",
877 starting_wavefunction_directory_,
880 int kpoint_states_from_saved_bands = 0;
882 double atomic_wfc_ms = 0.0;
883 double rotate_ms = 0.0;
885 ++kpoint_index_state) {
886 int spin_index = kpoint_index_state / number_of_kpoints;
887 int kpoint_index = kpoint_index_state % number_of_kpoints;
889 auto timer_awfc_start = std::chrono::high_resolution_clock::now();
891 std::vector<std::vector<Complex>> atomic_wavefunctions;
892 if (reuse_saved_wavefunctions &&
894 ++kpoint_states_from_saved_bands;
905 atomic_wavefunctions);
907 auto timer_awfc_end = std::chrono::high_resolution_clock::now();
909 std::chrono::duration<double, std::milli>(timer_awfc_end - timer_awfc_start)
920 starting_guess_potential[
static_cast<std::size_t
>(spin_index)],
926 atomic_wavefunctions,
929 auto timer_rotate_end = std::chrono::high_resolution_clock::now();
931 std::chrono::duration<double, std::milli>(timer_rotate_end - timer_awfc_end)
935 auto timer_4 = std::chrono::high_resolution_clock::now();
936 if (reuse_saved_wavefunctions) {
938 Real reused_states = kpoint_states_from_saved_bands;
942 log::info(
" Starting wavefunctions = saved bands at {} of {} k-point(s) from "
944 std::lround(reused_states),
945 std::lround(all_states),
946 starting_wavefunction_directory_);
953 std::chrono::duration<double, std::milli>(timer_1 - timer_0).count());
955 std::chrono::duration<double, std::milli>(timer_2 - timer_1).count());
957 std::chrono::duration<double, std::milli>(timer_3 - timer_2).count());
958 log::debug(
" atomic_wfc_gen: {:.1f} ms", atomic_wfc_ms);
959 log::debug(
" rotate_wfc: {:.1f} ms", rotate_ms);
961 std::chrono::duration<double, std::milli>(timer_4 - timer_3).count());
973 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; ++kpoint_index) {
988 for (
int kpoint_index = 0; kpoint_index < number_of_kpoints; ++kpoint_index) {
1002 ++kpoint_index_state) {
1003 int spin_index = kpoint_index_state / number_of_kpoints;
1004 int kpoint_index = kpoint_index_state % number_of_kpoints;
1006 if (kpoint_index == 0) {
1099 std::vector<int> manifold_row_offsets(number_of_manifolds);
1100 int total_hubbard_orbitals = 0;
1103 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds;
1105 manifold_row_offsets[manifold_index] = offset;
1109 total_hubbard_orbitals = offset;
1113 std::vector<std::vector<std::vector<Complex>>> occupation_matrices(number_of_manifolds);
1114 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds; ++manifold_index) {
1117 occupation_matrices[manifold_index].assign(
1119 std::vector<Complex>(
static_cast<size_t>(manifold_size) * manifold_size,
1124 ++kpoint_index_state) {
1125 int spin_index = kpoint_index_state / number_of_kpoints;
1126 int kpoint_index = kpoint_index_state % number_of_kpoints;
1133 band_occupations[band_index] =
1135 kpoint_index_state, band_index);
1144 std::vector<int> occupied_band_indices;
1147 occupied_band_indices.push_back(band_index);
1150 int number_of_occupied_bands =
static_cast<int>(occupied_band_indices.size());
1152 std::vector<Complex> packed_projectors(
static_cast<size_t>(plane_waves_at_kpoint) *
1153 total_hubbard_orbitals);
1154 for (
int orbital_index = 0; orbital_index < total_hubbard_orbitals; ++orbital_index) {
1155 const Complex* projector = hubbard_projectors[orbital_index];
1156 std::copy(projector,
1157 projector + plane_waves_at_kpoint,
1158 packed_projectors.begin() +
1159 static_cast<size_t>(orbital_index) * plane_waves_at_kpoint);
1162 std::vector<Complex> occupied_wavefunctions(
static_cast<size_t>(plane_waves_at_kpoint) *
1163 number_of_occupied_bands);
1164 for (
int occupied_band_index = 0; occupied_band_index < number_of_occupied_bands;
1165 ++occupied_band_index) {
1166 int band_index = occupied_band_indices[occupied_band_index];
1167 size_t offset =
static_cast<size_t>(occupied_band_index) * plane_waves_at_kpoint;
1168 for (
int g_index = 0; g_index < plane_waves_at_kpoint; ++g_index) {
1169 occupied_wavefunctions[offset + g_index] =
1174 std::vector<Complex> batched_overlaps;
1176 total_hubbard_orbitals,
1177 number_of_occupied_bands,
1178 packed_projectors.data(),
1179 occupied_wavefunctions.data(),
1192 plane_waves_at_kpoint,
1193 total_hubbard_orbitals,
1194 number_of_occupied_bands,
1195 packed_projectors.data(),
1196 occupied_wavefunctions.data(),
1203 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds;
1207 int row_offset = manifold_row_offsets[manifold_index];
1214 static_cast<size_t>(manifold_size));
1215 for (
int occupied_band_index = 0; occupied_band_index < number_of_occupied_bands;
1216 ++occupied_band_index) {
1218 static_cast<size_t>(occupied_band_indices[occupied_band_index]);
1219 size_t column_offset =
1220 static_cast<size_t>(occupied_band_index) * total_hubbard_orbitals;
1221 for (
int m = 0; m < manifold_size; ++m) {
1222 overlaps(band_index,
static_cast<size_t>(m)) =
1223 batched_overlaps[column_offset +
static_cast<size_t>(row_offset) +
1224 static_cast<size_t>(m)];
1244 occupation_matrices[manifold_index][spin_index]);
1252 std::vector<Real> flat_buffer;
1253 for (
const auto& per_spin_matrices : occupation_matrices) {
1254 for (
const auto& matrix : per_spin_matrices) {
1255 for (
const auto& element : matrix) {
1256 flat_buffer.push_back(element.real());
1257 flat_buffer.push_back(element.imag());
1263 size_t flat_index = 0;
1264 for (
auto& per_spin_matrices : occupation_matrices) {
1265 for (
auto& matrix : per_spin_matrices) {
1266 for (
auto& element : matrix) {
1267 element =
Complex(flat_buffer[flat_index], flat_buffer[flat_index + 1]);
1306 std::vector<HubbardManifoldLayout> layouts;
1307 layouts.reserve(number_of_manifolds);
1309 layouts.push_back({manifold.atom_index,
1310 manifold.angular_momentum,
1311 static_cast<int>(manifold.orbital_indices.size())});
1329 bool seeding_already_reported =
1331 1 + std::max(0,
config().hubbard_fixed_occupation_iterations);
1332 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds;
1335 int manifold_size =
static_cast<int>(manifold.orbital_indices.size());
1337 for (
const auto& directive :
config().hubbard_starting_eigenvalues) {
1338 if (directive.species_symbol != atom_species)
1340 if (directive.eigenvalue_index >= manifold_size)
1341 throw std::runtime_error(
"hubbard starting eigenvalue " +
1342 std::to_string(directive.eigenvalue_index + 1) +
1343 " for species '" + directive.species_symbol +
1344 "' exceeds the manifold size " +
1345 std::to_string(manifold_size));
1347 occupation_matrices[manifold_index]
1348 [
static_cast<size_t>(directive.spin_index)],
1350 directive.eigenvalue_index,
1352 if (!seeding_already_reported)
1353 log::info(
" DFT+U: seeding atom {} spin {} eigenvalue {} -> {:.4f}",
1354 manifold.atom_index + 1,
1355 directive.spin_index + 1,
1356 directive.eigenvalue_index + 1,
1357 directive.target_occupation);
1378 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds; ++manifold_index) {
1384 for (
int m = 0; m < manifold_size; m++)
1385 trace += occupation_matrices[manifold_index][spin_index]
1386 [
static_cast<size_t>(m) * manifold_size + m]
1388 traces += fmt::format(
"{}{:.4f}", spin_index == 0 ?
"" :
" / ",
trace);
1412 log::info(
" DFT+U: occupation matrix is not converging monotonically; "
1413 "damping it at mixing_beta from here");
1431 Real total_hubbard_energy = 0.0;
1432 Real total_hubbard_potential_energy = 0.0;
1434 std::fill(buffer.begin(), buffer.end(),
Complex(0.0, 0.0));
1436 for (
size_t manifold_index = 0; manifold_index < number_of_manifolds; ++manifold_index) {
1439 int row_offset = manifold_row_offsets[manifold_index];
1447 auto raw_occupation_matrix = damped_occupation_matrices[manifold_index][spin_index];
1448 for (
auto& element : raw_occupation_matrix) {
1449 element /= spin_degeneracy_factor;
1452 manifold_size, u_rydberg, raw_occupation_matrix);
1453 total_hubbard_energy +=
result.energy * spin_degeneracy_factor;
1465 Real manifold_potential_energy = 0.0;
1466 for (
int m = 0; m < manifold_size; ++m) {
1467 for (
int m_prime = 0; m_prime < manifold_size; ++m_prime) {
1468 manifold_potential_energy +=
1469 (
result.d_matrix[
static_cast<size_t>(m * manifold_size + m_prime)] *
1470 raw_occupation_matrix[
static_cast<size_t>(m_prime * manifold_size +
1475 total_hubbard_potential_energy +=
1476 manifold_potential_energy * spin_degeneracy_factor;
1479 for (
int m = 0; m < manifold_size; ++m) {
1480 for (
int m_prime = 0; m_prime < manifold_size; ++m_prime) {
1481 int global_row = row_offset + m;
1482 int global_column = row_offset + m_prime;
1484 combined_buffer[
static_cast<size_t>(global_row) +
1485 static_cast<size_t>(global_column) *
1487 result.d_matrix[
static_cast<size_t>(m * manifold_size + m_prime)];
1511 hubbard_potential_energy();
1529 return hubbard_potential_energy_;
1543 int total_kpoint_states) {
1544 int next_kpoint_state_index = current_kpoint_state_index + 1;
1545 if (next_kpoint_state_index >= total_kpoint_states) {
1549 int number_of_kpoints = kpoint_grid().number_of_kpoints();
1550 int current_kpoint_index = current_kpoint_state_index % number_of_kpoints;
1551 int next_kpoint_index = next_kpoint_state_index % number_of_kpoints;
1554 int current_spin_index = current_kpoint_state_index / number_of_kpoints;
1555 int next_spin_index = next_kpoint_state_index / number_of_kpoints;
1556 if (current_spin_index != next_spin_index) {
1560 int source_number_of_plane_waves = number_of_plane_waves(current_kpoint_index);
1561 int target_number_of_plane_waves = number_of_plane_waves(next_kpoint_index);
1562 int coefficients_to_copy =
1563 std::min(source_number_of_plane_waves, target_number_of_plane_waves);
1565 for (
int band_index = 0; band_index < number_of_bands_; ++band_index) {
1566 const Complex* source_band_data =
1567 quantum_system_.wavefunction_band_data(current_kpoint_state_index, band_index);
1569 quantum_system_.wavefunction_band_data(next_kpoint_state_index, band_index);
1572 std::copy(source_band_data, source_band_data + coefficients_to_copy, target_band_data);
1575 if (target_number_of_plane_waves > source_number_of_plane_waves) {
1576 std::fill(target_band_data + coefficients_to_copy,
1577 target_band_data + target_number_of_plane_waves,
1582 quantum_system_.set_eigenvalue(
1583 next_kpoint_state_index,
1585 quantum_system_.eigenvalue(current_kpoint_state_index, band_index));
1597 int target_kpoint_state_index) {
1598 int number_of_kpoints = kpoint_grid().number_of_kpoints();
1599 int source_kpoint_index = source_kpoint_state_index % number_of_kpoints;
1600 int target_kpoint_index = target_kpoint_state_index % number_of_kpoints;
1602 int source_number_of_plane_waves = number_of_plane_waves(source_kpoint_index);
1603 int target_number_of_plane_waves = number_of_plane_waves(target_kpoint_index);
1604 int coefficients_to_copy =
1605 std::min(source_number_of_plane_waves, target_number_of_plane_waves);
1607 for (
int band_index = 0; band_index < number_of_bands_; ++band_index) {
1608 const Complex* source_band_data =
1609 quantum_system_.wavefunction_band_data(source_kpoint_state_index, band_index);
1611 quantum_system_.wavefunction_band_data(target_kpoint_state_index, band_index);
1613 std::copy(source_band_data, source_band_data + coefficients_to_copy, target_band_data);
1615 if (target_number_of_plane_waves > source_number_of_plane_waves) {
1616 std::fill(target_band_data + coefficients_to_copy,
1617 target_band_data + target_number_of_plane_waves,
1621 quantum_system_.set_eigenvalue(
1622 target_kpoint_state_index,
1624 quantum_system_.eigenvalue(source_kpoint_state_index, band_index));
1641 if (band_path_.empty() || band_path_points_per_segment_ <= 0) {
1644 int number_of_segments =
static_cast<int>(band_path_.size()) - 1;
1645 if (number_of_segments <= 0) {
1652 int last_kpoint_index = number_of_segments * band_path_points_per_segment_;
1653 if (kpoint_index >= last_kpoint_index) {
1657 return (kpoint_index % band_path_points_per_segment_) == 0;
1679 int number_of_kpoint_states) {
1680 if (number_of_kpoints <= 2) {
1689 std::vector<int> edge_kpoint_indices;
1690 edge_kpoint_indices.push_back(0);
1692 if (!band_path_.empty() && band_path_points_per_segment_ > 0) {
1693 int number_of_segments =
static_cast<int>(band_path_.size()) - 1;
1694 for (
int segment_index = 1; segment_index < number_of_segments; ++segment_index) {
1695 int boundary_kpoint_index = segment_index * band_path_points_per_segment_;
1696 if (boundary_kpoint_index < number_of_kpoints) {
1697 edge_kpoint_indices.push_back(boundary_kpoint_index);
1707 const int backward_sweep_depth = 5;
1709 for (
int spin_index = 0; spin_index < number_of_spin_components(); ++spin_index) {
1710 for (
int edge_kpoint_index : edge_kpoint_indices) {
1716 std::min(edge_kpoint_index + backward_sweep_depth, number_of_kpoints - 1);
1717 int seed_kpoint_index = std::min(sweep_end + 1, number_of_kpoints - 1);
1723 for (
int target_kpoint_index = sweep_end; target_kpoint_index >= edge_kpoint_index;
1724 --target_kpoint_index) {
1726 int source_state_index = spin_index * number_of_kpoints + seed_kpoint_index;
1727 int target_state_index = spin_index * number_of_kpoints + target_kpoint_index;
1729 propagate_wavefunctions_backward(source_state_index, target_state_index);
1731 diagonalizer_->solve(target_state_index,
1732 target_kpoint_index,
1733 number_of_plane_waves(target_kpoint_index),
1735 g_vector_indices(target_kpoint_index),
1736 kinetic_energy_squared()[target_kpoint_index],
1737 real_space_potential_[spin_index],
1738 crystal_structure(),
1741 *quantum_system_snapshot_,
1743 report_unconverged_solve(target_state_index);
1746 seed_kpoint_index = target_kpoint_index;
1760 if (!report_unconverged_bands_) {
1763 int unconverged = diagonalizer_->number_of_unconverged_bands();
1764 if (unconverged > 0) {
1765 log::warn(
"NSCF: k-point state {} kept {} of {} bands unconverged after the "
1766 "Davidson iteration cap; its eigenvalues and eigenvectors are not "
1767 "converged to the requested tolerance",
1776 return quantum_system_snapshot_->pseudopotential_basis().total_local_potential_g();
1779 return quantum_system_snapshot_->pseudopotential_basis().core_charge_density_reciprocal();
1795 if (!dispersion_energy_computed_) {
1799 dispersion_energy_computed_ =
true;
1803 charge_density_real_, number_of_spin_components(), local_ionic_potential_g());
1809 exchange_correlation_potential_g_ =
1817 if (cached_local_ionic_potential_real_.empty()) {
1818 planewave_basis_.rho_g_to_r(local_ionic_potential_g(),
1819 cached_local_ionic_potential_real_);
1828 if (!effective_potential_calculator_) {
1829 effective_potential_calculator_ =
1830 std::make_unique<NormConservingPlanewaveEffectivePotentialCalculator>(
1832 crystal_structure(),
1833 *exchange_correlation_,
1835 quantum_system_snapshot_->pseudopotential_basis()
1836 .core_charge_density_reciprocal());
1838 return *effective_potential_calculator_;
1843 quantum_system_snapshot_ =
1845 crystal_structure(), planewave_basis_, pseudopotential_set());
1857 const auto& plane_waves_per_kpoint = planewave_basis_.kpoint_number_of_plane_waves();
1859 plane_waves_per_kpoint.empty()
1861 : *std::max_element(plane_waves_per_kpoint.begin(), plane_waves_per_kpoint.end());
1864 quantum_system_snapshot_->pseudopotential_basis().total_number_of_projectors();
1887 int kpoint_index, std::vector<std::vector<Complex>>& starting_wavefunctions)
const {
1888 std::vector<std::vector<Complex>> saved_bands = read_saved_bands(kpoint_index);
1889 Real ranks_without_saved_bands = saved_bands.empty() ? 1.0 : 0.0;
1890 execution_policy_->reduce_within_pool_scalar(ranks_without_saved_bands);
1891 if (ranks_without_saved_bands > 0.0) {
1894 starting_wavefunctions = std::move(saved_bands);
1911 const int global_kpoint_index = execution_policy_->global_kpoint_index(kpoint_index);
1912 const std::string path = starting_wavefunction_directory_ +
"/wfc" +
1913 std::to_string(global_kpoint_index + 1) +
".dat";
1914 std::error_code exists_error;
1915 if (!std::filesystem::exists(path, exists_error)) {
1921 }
catch (
const std::exception& error) {
1922 log::debug(
" Saved bands not used: {}", error.what());
1926 reader.
is_gamma_only() != planewave_basis_.is_gamma_only()) {
1931 const Matrix3x3 reciprocal_vectors_bohr = crystal_structure().reciprocal_vectors_bohr();
1932 const auto& kpoint = kpoint_grid()[kpoint_index];
1933 constexpr Real tolerance_inverse_bohr = 1.0e-10;
1934 for (
int dimension = 0; dimension < 3; dimension++) {
1935 const Real kpoint_cartesian =
1936 kpoint.coordinates.x * reciprocal_vectors_bohr[0][dimension] +
1937 kpoint.coordinates.y * reciprocal_vectors_bohr[1][dimension] +
1938 kpoint.coordinates.z * reciprocal_vectors_bohr[2][dimension];
1940 tolerance_inverse_bohr) {
1943 for (
int vector_index = 0; vector_index < 3; vector_index++) {
1945 reciprocal_vectors_bohr[vector_index][dimension]) >
1946 tolerance_inverse_bohr) {
1953 auto miller_key = [](std::int64_t h, std::int64_t k, std::int64_t l) {
1954 constexpr std::int64_t offset = 1 << 20;
1955 constexpr std::int64_t span = 1 << 21;
1956 return ((h + offset) * span + (k + offset)) * span + (l + offset);
1959 std::unordered_map<std::int64_t, int> saved_position;
1960 saved_position.reserve(saved_millers.size());
1961 for (
int position = 0; position < static_cast<int>(saved_millers.size()); position++) {
1962 saved_position.emplace(miller_key(saved_millers[position].x,
1963 saved_millers[position].y,
1964 saved_millers[position].z),
1967 const auto& g_vectors = planewave_basis_.g_vectors();
1968 const auto& local_g_indices = g_vector_indices(kpoint_index);
1969 const int local_plane_waves = number_of_plane_waves(kpoint_index);
1970 std::vector<int> source_position(
static_cast<std::size_t
>(local_plane_waves));
1971 for (
int plane_wave = 0; plane_wave < local_plane_waves; plane_wave++) {
1972 const auto& miller = g_vectors[local_g_indices[plane_wave]].miller;
1973 const auto found = saved_position.find(
1974 miller_key(std::lround(miller.x), std::lround(miller.y), std::lround(miller.z)));
1975 if (found == saved_position.end()) {
1978 source_position[
static_cast<std::size_t
>(plane_wave)] = found->second;
1981 std::vector<std::vector<Complex>> bands(
1982 static_cast<std::size_t
>(number_of_bands_),
1983 std::vector<Complex>(
static_cast<std::size_t
>(local_plane_waves)));
1984 for (
int band = 0; band < number_of_bands_; band++) {
1986 for (
int plane_wave = 0; plane_wave < local_plane_waves; plane_wave++) {
1987 bands[band][plane_wave] = coefficients[source_position[plane_wave]];
1994 log::info(
" number of KB projectors = {}",
1995 quantum_system_snapshot_->pseudopotential_basis().total_number_of_projectors());
1996 log::info(
" Starting wavefunctions = {} atomic wfcs",
1997 number_of_atomic_wavefunctions);
2009 std::vector<Real> species_magnetization(crystal_structure().number_of_species(), 0.0);
2010 if (starting_magnetization_.empty()) {
2011 species_magnetization.assign(species_magnetization.size(),
2013 return species_magnetization;
2015 for (
size_t species_index = 0; species_index < starting_magnetization_.size() &&
2016 species_index < species_magnetization.size();
2018 species_magnetization[species_index] = starting_magnetization_[species_index];
2020 return species_magnetization;
2024 int number_of_g_vectors = planewave_basis_.number_of_g_vectors();
2025 Real cell_volume = crystal_structure().cell_volume();
2026 bool spin_polarized = number_of_spin_components() == 2;
2028 std::vector<Real> species_magnetization;
2029 std::vector<Complex> magnetization_density_g;
2030 if (spin_polarized) {
2031 species_magnetization = effective_species_magnetizations();
2032 magnetization_density_g.assign(number_of_g_vectors,
Complex(0.0, 0.0));
2033 if (!atomic_starting_magnetization_.empty() &&
2034 static_cast<int>(atomic_starting_magnetization_.size()) !=
2035 crystal_structure().number_of_atoms())
2036 throw std::runtime_error(
"atomic_starting_magnetization lists " +
2037 std::to_string(atomic_starting_magnetization_.size()) +
2038 " values but the cell has " +
2039 std::to_string(crystal_structure().number_of_atoms()) +
2043 charge_density_g_.resize(number_of_g_vectors,
Complex(0.0, 0.0));
2044 for (
int g_vector_index = 0; g_vector_index < number_of_g_vectors; ++g_vector_index) {
2045 for (
int atom_index = 0; atom_index < crystal_structure().number_of_atoms();
2047 int species_type = crystal_structure().species_type_index(atom_index);
2049 crystal_structure().convert_from_crystal_to_cartesian(atom_index);
2050 const auto& g_vector = planewave_basis_.g_vectors()[g_vector_index];
2054 quantum_system_snapshot_->pseudopotential_basis().atomic_charge_density_g(
2055 species_type)[g_vector_index] *
2056 structure_factor / cell_volume;
2057 charge_density_g_[g_vector_index] += atomic_contribution;
2058 if (spin_polarized) {
2064 Real atom_magnetization = atomic_starting_magnetization_.empty()
2065 ? species_magnetization[species_type]
2066 : atomic_starting_magnetization_[atom_index];
2067 magnetization_density_g[g_vector_index] +=
2068 atom_magnetization * atomic_contribution;
2073 Real total_starting_charge = charge_density_g_[0].real() * cell_volume;
2075 Real scaling_factor = number_of_electrons_ / total_starting_charge;
2076 for (
int g_vector_index = 0; g_vector_index < number_of_g_vectors; ++g_vector_index) {
2077 charge_density_g_[g_vector_index] *= scaling_factor;
2079 magnetization_density_g[g_vector_index] *= scaling_factor;
2083 int local_grid_points = planewave_basis_.fft_rho().local_grid_points();
2084 charge_density_real_.resize(number_of_spin_components());
2086 if (!spin_polarized) {
2087 planewave_basis_.rho_g_to_r(charge_density_g_, charge_density_real_[0]);
2088 on_charge_density_initialized();
2093 std::vector<Real> total_charge_density_real;
2094 std::vector<Real> magnetization_density_real;
2095 planewave_basis_.rho_g_to_r(charge_density_g_, total_charge_density_real);
2096 planewave_basis_.rho_g_to_r(magnetization_density_g, magnetization_density_real);
2098 charge_density_real_[0].resize(local_grid_points);
2099 charge_density_real_[1].resize(local_grid_points);
2100 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
2101 charge_density_real_[0][grid_index] = 0.5 * (total_charge_density_real[grid_index] +
2102 magnetization_density_real[grid_index]);
2103 charge_density_real_[1][grid_index] = 0.5 * (total_charge_density_real[grid_index] -
2104 magnetization_density_real[grid_index]);
2106 on_charge_density_initialized();
const std::string & element(int atom_index) const
virtual int total_grid_points() const =0
Real residual() const
||n_fresh - n_damped||^2 from the last blend; huge until one has run.
const HubbardOccupationMatrices & blend(const HubbardOccupationMatrices &fresh, Real mixing_beta, Real convergence_threshold)
bool damping_active() const
Whether non-monotone progress has switched damping on for this run.
int number_of_kpoints() const
virtual void prepare_hamiltonian()
const KohnShamSCFIteratorConfig & config() const
const std::vector< Real > & charge_density_real() const
Real total_energy() const override
std::unique_ptr< XCFunctional > exchange_correlation_
std::vector< Complex > total_potential_g_
Crystal & crystal_structure() const
bool has_preloaded_charge_density_
std::vector< std::vector< Real > > charge_density_real_
const std::vector< Complex > & exchange_correlation_potential_g() const
std::vector< Complex > charge_density_g_
const XCFunctional & exchange_correlation() const
std::vector< std::vector< Real > > real_space_potential_
bool preloaded_charge_density_is_a_starting_guess_
Set by offer_starting_charge_density(): a density that need not fit.
std::vector< std::vector< Complex > > total_potential_g_by_spin_
T * data()
Returns the underlying flat data pointer.
void compute_atomic_wavefunctions(int kpoint_index, int number_of_plane_waves, int number_of_bands, const std::vector< int > &g_vector_indices, const Crystal &crystal_structure, const KPointsGrid &kpoint_grid, const PlanewaveBasis &planewave_basis, const PseudopotentialSet &pseudopotential_set, std::vector< std::vector< Complex > > &atomic_wavefunctions)
void initialize_interpolation_table(const PseudopotentialSet &pseudopotential_set, Real cell_volume)
void rotate_wavefunctions(int kpoint_index, int kpoint_index_state, int number_of_plane_waves, int number_of_bands, const std::vector< int > &g_vector_indices, const std::vector< Real > &kinetic_energy_squared, const std::vector< Real > &smooth_potential, const Crystal &crystal_structure, const KPointsGrid &kpoint_grid, const PlanewaveBasis &planewave_basis, const execution::PlanewaveExecutionPolicy &execution_policy, const NormConservingPlanewaveKohnShamQuantumSystem &pseudopotential_quantum_system, const std::vector< std::vector< Complex > > &atomic_wavefunctions, PlanewaveKohnShamQuantumSystem &quantum_system, const Matrix< Complex > &precomputed_kleinman_bylander_potential)
bool is_gamma_only() const
EffectivePotentialResult compute(const std::vector< std::vector< Real > > &charge_density_real, int number_of_spin_components, const std::vector< Complex > &local_ionic_potential_g) const
Complex wavefunction(int kpoint_index, int band_index, int g_vector_index) const
Real occupation_by_kpoint_state_index_and_band_index(int kpoint_state_index, int band_index) const
const std::vector< std::vector< int > > & g_vector_indices() const
const std::optional< Magnetization > & magnetization() const
PlanewaveBasis planewave_basis_
const KPointsGrid & kpoint_grid() const
virtual void release_scf_workspace()
std::string diagonalization_method_
int number_of_kpoint_states() const override
PlanewaveKohnShamQuantumSystem quantum_system_
const execution::PlanewaveExecutionPolicy & execution_policy() const
const std::vector< std::vector< Real > > & kinetic_energy_squared() const
Real compute_double_counting_correction() const override
void construct_density_from_states() override
void scale_loaded_charge_density_to_electron_count()
Rescale the loaded density so it integrates to this system's electron count.
std::unique_ptr< PlanewaveDiagonalizer > diagonalizer_
virtual void on_charge_density_initialized()
const std::vector< int > & number_of_plane_waves() const
std::optional< int > nscf_override_maximum_iterations_
std::optional< Real > nscf_override_tolerance_
Matrix< Real > global_eigenvalues() const
bool loaded_charge_density_fits_grid() const
void update_effective_potential() override
void preload_single_particle_states()
void initialize_representation() override
execution::PlanewaveExecutionPolicy * execution_policy_
Real spin_degeneracy() const
void preload_charge_density()
static void report_memory_estimate(const PlanewaveMemoryEstimate &estimate)
void report_unconverged_solve(int kpoint_index_state) const
bool is_at_band_path_segment_boundary(int kpoint_index) const
void fix_edge_kpoints_with_backward_propagation(int number_of_kpoints, int number_of_kpoint_states)
void initialize_single_particle_states() override
std::shared_ptr< NormConservingPlanewaveKohnShamQuantumSystem > quantum_system_snapshot_
virtual std::vector< Matrix< Real > > one_center_occupations() const
void construct_density_from_states() override
bool symmetry_operations_cached_
Real hubbard_occupation_residual_
std::vector< std::vector< Complex > > read_saved_bands(int kpoint_index) const
std::vector< Real > atomic_starting_magnetization_
PlanewavePseudopotentialKohnShamSCFIterator(KohnShamSCFIteratorConfig config)
NormConservingPlanewaveKohnShamEnergies energies_
void create_norm_conserving_quantum_system_snapshot()
bool take_saved_starting_wavefunctions(int kpoint_index, std::vector< std::vector< Complex > > &starting_wavefunctions) const
void initialize_representation() override
virtual const Matrix< Real > & projector_overlap_coefficients() const
void log_pseudopotential_summary(int number_of_atomic_wavefunctions) const
std::vector< q3::Matrix< Complex > > cached_kleinman_bylander_projectors_
Cached KB projectors per k-point (reused by the projector overlap accumulation).
NormConservingPlanewaveEffectivePotentialCalculator & effective_potential_calculator()
NormConservingPlanewaveKohnShamEnergies & energies_mutable() override
void set_diagonalizer_tolerance_for_nscf(Real tolerance)
const NormConservingPlanewaveKohnShamQuantumSystem & norm_conserving_quantum_system() const
void initialize_charge_density_from_atomic_superposition()
void propagate_wavefunctions_to_next_kpoint(int current_kpoint_state_index, int total_kpoint_states)
Real hubbard_potential_energy() const
std::vector< Real > starting_magnetization_
const std::vector< SymmetryOperation > & cached_symmetry_operations() const
std::vector< HubbardManifold > hubbard_manifolds_
DFT+U (Hubbard): resolved atom/shell manifolds; empty means no correction is active.
std::vector< q3::Matrix< Complex > > cached_hubbard_projectors_
Real compute_double_counting_correction() const override
std::vector< std::pair< std::string, Vector3D > > band_path_
void set_diagonalizer_maximum_iterations_for_nscf(int maximum_iterations)
int band_path_points_per_segment_
void release_scf_workspace() override
void initialize_charge_density() override
bool is_iteration_converged() const override
const std::vector< Complex > & local_ionic_potential_g() const override
void solve_single_particle_states() override
HubbardOccupationMixer hubbard_occupation_mixer_
Owns the damping/Anderson state; see HubbardOccupationMixer.
virtual bool requires_one_center_occupations() const
const PseudopotentialSet & pseudopotential_set() const
const NormConservingPlanewaveKohnShamEnergies & energies() const override
std::vector< std::vector< Real > > hubbard_occupation_traces_
void set_owned_pseudopotential_set(PseudopotentialSet pseudopotential_set)
Transfer ownership of a PseudopotentialSet into this iterator.
int total_hubbard_orbitals_
void report_memory_estimate(int number_of_atomic_wavefunctions) const
const std::vector< Complex > & core_charge_density_g() const override
int hubbard_seed_iterations_remaining_
const std::vector< std::vector< Real > > & hubbard_occupation_traces() const
Real hubbard_potential_energy_
Σ_σ Tr[V_U^σ n^σ]; see hubbard_potential_energy().
std::vector< Complex > valence_exchange_correlation_potential_g_of(const std::vector< std::vector< Real > > &charge_density_real)
void compute_effective_potential_from_density() override
~PlanewavePseudopotentialKohnShamSCFIterator() override=default
std::vector< std::vector< Complex > > hubbard_d_matrix_per_spin_
std::vector< SymmetryOperation > cached_symmetry_operations_
virtual void load_one_center_occupations(const std::vector< Matrix< Real > > &occupations_by_spin)
void offer_starting_wavefunctions(std::string save_directory)
const PseudopotentialSet * pseudopotential_set_
void propagate_wavefunctions_backward(int source_kpoint_state_index, int target_kpoint_state_index)
void accumulate_hubbard_occupation_and_potential()
void write_checkpoints(const std::string &output_directory, const std::string &prefix) const override
void refresh_quantum_system_snapshot()
NormConservingPlanewaveKohnShamSCFState result() const override
std::vector< Real > effective_species_magnetizations() const
bool save(const std::string &filename, const KohnShamQuantumSystemSnapshot &snapshot, bool save_wavefunctions=false) const override
const std::vector< Complex > & band_coefficients(int band_index) const
Coefficients of one band, parallel to miller_indices().
const Vector3D & kpoint_coordinates() const
Cartesian coordinates, in 1/bohr, of the k-point this file belongs to.
int number_of_bands() const
const std::vector< IntegerVector3D > & miller_indices() const
bool is_gamma_only() const
void read(const std::string &path)
Read path, replacing whatever this reader held; throws on a malformed file.
const Matrix3x3 & reciprocal_lattice_vectors() const
const QuantumSystem< QuantumStateType > * preloaded_quantum_system_
Real convergence_threshold_
virtual bool is_iteration_converged() const =0
int number_of_spin_components() const
bool is_converged() const
static std::vector< SymmetryOperation > get_symmetry_operations(const Crystal &crystal, Real symmetry_precision=math::tolerances::default_symmetry_precision)
virtual void reduce_group_distributed_result(ComplexValue *, int) const
virtual bool is_root() const =0
virtual void reduce_within_group(ComplexValue *data, int number_of_elements) const =0
virtual void reduce_vector(std::vector< Real > &values) const =0
virtual bool each_process_owns_whole_kpoints() const =0
virtual int number_of_pools() const =0
virtual void reduce_scalar(Real &value) const =0
constexpr Real default_starting_magnetization
void debug(spdlog::format_string_t< Args... > fmt, Args &&... args)
void warn(spdlog::format_string_t< Args... > fmt, Args &&... args)
void info(spdlog::format_string_t< Args... > fmt, Args &&... args)
void trace(spdlog::format_string_t< Args... > fmt, Args &&... args)
constexpr double numerical_zero_threshold
constexpr double zero_vector_magnitude_threshold
constexpr double occupation_threshold
void accumulate_hubbard_occupation_matrix(int number_of_bands, int manifold_size, const Matrix< Complex > &overlaps, const std::vector< Real > &band_occupations, Real kpoint_weight, std::vector< Complex > &occupation_matrix)
void build_atomic_orbitals_g_space(int kpoint_index, int number_of_plane_waves, const std::vector< int > &g_vector_indices, const Crystal &crystal_structure, const KPointsGrid &kpoint_grid, const PlanewaveBasis &planewave_basis, const PseudopotentialSet &pseudopotential_set, const std::vector< std::vector< std::vector< Real > > > &atomic_wavefunction_table, Real q_spacing, int number_of_q_points, std::vector< std::vector< Complex > > &orbitals)
int count_atomic_orbitals(const Crystal &crystal_structure, const PseudopotentialSet &pseudopotential_set)
void apply_hubbard_starting_eigenvalue(std::vector< Complex > &matrix, int size, int eigenvalue_index, Real value)
void compute_hubbard_projector_overlaps(int number_of_plane_waves, int total_hubbard_orbitals, int number_of_bands, const Complex *packed_orbitals, const Complex *band_functions, std::vector< Complex > &overlaps)
void convert_gamma_only_projector_overlaps_to_full_sphere(int number_of_plane_waves, int total_hubbard_orbitals, int number_of_bands, const Complex *packed_orbitals, const Complex *band_functions, int g_zero_index, bool band_functions_carry_g_component, std::vector< Complex > &overlaps)
void lowdin_orthogonalize_orbitals(std::vector< std::vector< Complex > > &orbitals, std::vector< Complex > overlap_column_major)
std::vector< Complex > compute_smooth_grid_potential_from_dense(const std::vector< Real > &dense_real_space_potential, const PlanewaveBasis &planewave_basis)
HubbardEnergyAndPotential compute_hubbard_energy_and_potential(int manifold_size, Real u_rydberg, const std::vector< Complex > &occupation_matrix)
std::unique_ptr< PlanewaveKohnShamChargeDensityCheckpoint > create_charge_density_checkpoint(const NormConservingPlanewaveKohnShamSCFState &scf_state, const std::string &format="qe")
void symmetrize_hubbard_occupation_matrices_under_time_reversal(std::vector< std::vector< std::vector< Complex > > > &occupation_matrices)
Complex compute_phase_factor(Real phase)
Compute e^{-iφ} = cos(φ) - i·sin(φ) (standard structure factor phase).
void symmetrize_hubbard_occupation_matrices(const Crystal &crystal_structure, const std::vector< SymmetryOperation > &symmetry_operations, const std::vector< HubbardManifoldLayout > &layouts, std::vector< std::vector< std::vector< Complex > > > &occupation_matrices)
std::vector< AtomicOrbitalLabel > enumerate_atomic_orbitals(const Crystal &crystal_structure, const PseudopotentialSet &pseudopotential_set)
std::vector< Real > inverse_fft_smooth_potential(const std::vector< Complex > &full_smooth_potential_g, const PlanewaveBasis &planewave_basis)
std::unique_ptr< OverlapOperator > create_overlap_operator(const Crystal &crystal_structure, const NormConservingPlanewaveKohnShamQuantumSystem &quantum_system, const Matrix< Complex > &kleinman_bylander_potential, const execution::ExecutionPolicy &execution_policy)
void compute_kleinman_bylander_projectors(const Vector3D &k_crystal, const Crystal &crystal_structure, const PlanewaveBasis &planewave_basis, const PseudopotentialSet &pseudopotential_set, const BetaFunctionTable &beta_function_table, const std::vector< int > &g_vector_indices, int number_of_plane_waves, int total_number_of_projectors, Matrix< Complex > &kleinman_bylander_potential)
std::unique_ptr< PlanewaveKohnShamWavefunctionCheckpoint > create_wavefunction_checkpoint(const NormConservingPlanewaveKohnShamSCFState &scf_state, const std::string &format="qe")
std::vector< std::vector< std::vector< Real > > > tabulate_atomic_wavefunctions_in_q_space(const PseudopotentialSet &pseudopotential_set, Real cell_volume, Real q_spacing, int number_of_q_points)
int find_g_zero_plane_wave_index(const PlanewaveBasis &planewave_basis, const std::vector< int > &plane_wave_indices, int number_of_plane_waves)
Real compute_ewald(const Crystal &crystal_structure, const PlanewaveBasis &planewave_basis)
std::complex< double > Complex
std::vector< HubbardManifold > resolve_hubbard_manifolds(const Crystal &crystal_structure, const std::vector< AtomicOrbitalLabel > &orbital_labels, const std::vector< HubbardSpecification > &specifications)
std::unique_ptr< DispersionCalculator > create_dispersion_calculator(const std::string &dispersion_correction, const Crystal &crystal_structure)
std::vector< Complex > charge_density_g
std::vector< Complex > total_potential_g
Real exchange_correlation_potential_energy
std::vector< std::vector< Complex > > total_potential_g_by_spin
std::vector< Complex > exchange_correlation_potential_g
Real exchange_correlation_energy
std::vector< std::vector< Real > > real_space_potential
Real exchange_correlation_potential_energy
Real exchange_correlation_energy
Matrix< Real > eigenvalues
std::vector< std::vector< Real > > effective_potential_real
std::vector< Matrix< Real > > one_center_occupations
int number_of_kpoint_states
std::vector< std::vector< Real > > charge_density_real
int number_of_spin_components
std::vector< Real > starting_magnetization
std::string hubbard_projector_type
std::vector< std::pair< std::string, Vector3D > > band_path
std::vector< Real > atomic_starting_magnetization
int band_path_points_per_segment
std::vector< HubbardStartingEigenvalue > hubbard_starting_eigenvalues
First-iteration occupation-eigenvalue overrides; empty = no seeding.
const PseudopotentialSet * pseudopotential_set
3×3 matrix stored row-major: row i = mat[i]
Real van_der_waals_energy
static std::shared_ptr< NormConservingPlanewaveKohnShamQuantumSystem > create_shared(const Crystal &crystal_structure, const PlanewaveBasis &planewave_basis, const PseudopotentialSet &pseudopotential_set)
std::vector< HubbardManifold > hubbard_manifolds
DFT+U (Hubbard) resolved manifolds at convergence; empty means no correction is active.
NormConservingPlanewaveKohnShamEnergies energies_data_
std::shared_ptr< NormConservingPlanewaveKohnShamQuantumSystem > quantum_system_snapshot_
std::string hubbard_projector_type
std::vector< std::vector< Complex > > hubbard_d_matrix_per_spin
std::vector< std::vector< Real > > charge_density_real
std::vector< Complex > total_potential_g
const KPointsGrid * kpoint_grid
const XCFunctional * exchange_correlation
std::vector< Complex > exchange_correlation_potential_g
const Crystal * crystal_structure
std::vector< std::vector< Real > > real_space_potential
const execution::PlanewaveExecutionPolicy * execution_policy
const PlanewaveBasis * planewave_basis
std::vector< std::vector< Complex > > total_potential_g_by_spin
std::vector< Complex > charge_density_g
static PlanewaveMemoryEstimate compute(const PlanewaveMemoryEstimateInputs &inputs)
void log_resident_checkpoint_debug(const std::string &label)
void log_resident_checkpoint(const std::string &label)
static ProfilingCounters & instance()
void release_unused_heap(const std::string &label)