Loading...
Searching...
No Matches
energy_calculator.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PlanewaveKohnShamEnergyCalculator — compute the band-structure energy and the smearing
5 * entropy contribution (-TS) from the current Kohn-Sham quantum state.
6 *
7 * Holds const references to the three read-only data sources it needs so that
8 * the iterator can simply call `compute_band_energy()` / `compute_smearing_entropy()`
9 * with a single `number_of_bands` and `number_of_spin_components` argument each,
10 * rather than threading every dependency through every call.
11 *
12 * Note: the double-counting correction (which depends on the mutable real-space
13 * density and potential arrays) remains in the iterator because it operates on
14 * state that changes every SCF iteration and is tightly coupled to those fields.
15 */
16
17#include <cmath>
18
23
24namespace q3 {
25
26/**
27 * Computes the band energy and smearing entropy contribution from the occupied
28 * Kohn-Sham eigenvalues and occupations.
29 *
30 * All referenced objects must outlive this calculator (non-owning references).
31 * The `smearing_scheme` pointer is nullable; pass `nullptr` for insulators.
32 */
34 public:
35 /**
36 * Construct a calculator bound to the given k-point grid, quantum system,
37 * and smearing scheme.
38 *
39 * @param kpoint_grid K-point grid providing coordinates and integration weights.
40 * @param quantum_system The Kohn-Sham quantum system (eigenvalues, occupations, Fermi energy).
41 * @param smearing_scheme Pointer to the active smearing scheme, or nullptr for no smearing.
42 */
44 const PlanewaveKohnShamQuantumSystem& quantum_system,
45 const SmearingScheme* smearing_scheme)
46 : kpoint_grid_(kpoint_grid)
47 , quantum_system_(quantum_system)
48 , smearing_scheme_(smearing_scheme) {}
49
50 /**
51 * Compute the band energy: Σ_{k,n} w_k * f_{k,n} * ε_{k,n} (Ry).
52 *
53 * @param number_of_bands Number of bands per k-point state.
54 * @param number_of_spin_components 1 (non-spin-polarized) or 2 (LSDA).
55 */
56 [[nodiscard]] Real compute_band_energy(int number_of_bands,
57 int number_of_spin_components) const {
58 int number_of_kpoints = kpoint_grid_.number_of_kpoints();
59 int number_of_kpoint_states = number_of_kpoints * number_of_spin_components;
60 Real band_energy = 0.0;
61
62 for (int kpoint_index_state = 0; kpoint_index_state < number_of_kpoint_states;
63 ++kpoint_index_state) {
64 int kpoint_index = kpoint_index_state % number_of_kpoints;
65 for (int band_index = 0; band_index < number_of_bands; ++band_index) {
66 Real occupation = quantum_system_.occupation_by_kpoint_state_index_and_band_index(
67 kpoint_index_state, band_index);
68 band_energy += kpoint_grid_[kpoint_index].weight * occupation *
69 quantum_system_.eigenvalue(kpoint_index_state, band_index);
70 }
71 }
72
73 return band_energy;
74 }
75
76 /**
77 * Compute the smearing entropy contribution -T*S (Ry).
78 *
79 * Returns 0.0 immediately if no smearing scheme is active.
80 *
81 * @param number_of_bands Number of bands per k-point state.
82 * @param number_of_spin_components 1 (non-spin-polarized) or 2 (LSDA).
83 */
84 [[nodiscard]] Real compute_smearing_entropy(int number_of_bands,
85 int number_of_spin_components) const {
86 if (!smearing_scheme_ || !smearing_scheme_->uses_smearing()) {
87 return 0.0;
88 }
89
90 Real smearing_width = smearing_scheme_->smearing_width();
91 int number_of_kpoints = kpoint_grid_.number_of_kpoints();
92 int number_of_kpoint_states = number_of_kpoints * number_of_spin_components;
93 Real entropy_contribution = 0.0;
94
95 for (int kpoint_index_state = 0; kpoint_index_state < number_of_kpoint_states;
96 ++kpoint_index_state) {
97 int kpoint_index = kpoint_index_state % number_of_kpoints;
98 for (int band_index = 0; band_index < number_of_bands; ++band_index) {
99 Real scaling_factor = (quantum_system_.eigenvalue(kpoint_index_state, band_index) -
100 quantum_system_.fermi_energy()) /
101 smearing_width;
102 entropy_contribution += kpoint_grid_[kpoint_index].weight * smearing_width *
103 smearing_scheme_->entropy_weight(scaling_factor);
104 }
105 }
106
107 return entropy_contribution;
108 }
109
110 private:
111 const KPointsGrid& kpoint_grid_;
112 const PlanewaveKohnShamQuantumSystem& quantum_system_;
113 const SmearingScheme* smearing_scheme_; // non-owning, nullable
114};
115
116} // namespace q3
int number_of_kpoints() const
Real compute_band_energy(int number_of_bands, int number_of_spin_components) const
PlanewaveKohnShamEnergyCalculator(const KPointsGrid &kpoint_grid, const PlanewaveKohnShamQuantumSystem &quantum_system, const SmearingScheme *smearing_scheme)
Real compute_smearing_entropy(int number_of_bands, int number_of_spin_components) const
Real occupation_by_kpoint_state_index_and_band_index(int kpoint_state_index, int band_index) const
Definition init.hpp:127
Real eigenvalue(int kpoint_state_index, int band_index) const
Definition init.hpp:118
Abstract interface for electronic smearing schemes.
Definition init.hpp:19
virtual Real entropy_weight(Real x) const =0
Compute the entropy contribution δ(x) weight.
Real smearing_width() const
Smearing width σ (degauss) in Ry.
Definition init.hpp:33
bool uses_smearing() const
Whether this scheme uses actual smearing (width > 0).
Definition init.hpp:38
double Real