39 const Crystal& crystal_structure,
48 planewave_basis, crystal_structure, exchange_correlation)) {}
53 int number_of_spin_components,
54 const std::vector<Complex>& local_ionic_potential_g)
const {
59 std::vector<Real> total_charge_density_real(local_grid_points, 0.0);
60 for (
int spin_index = 0; spin_index < number_of_spin_components; ++spin_index) {
61 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
62 total_charge_density_real[grid_index] +=
63 charge_density_real[spin_index][grid_index];
68 std::vector<Real> hartree_potential_real = compute_hartree_potential(output);
70 std::vector<std::vector<Real>> exchange_correlation_density;
71 std::vector<std::vector<Complex>> exchange_correlation_density_g;
73 number_of_spin_components,
74 exchange_correlation_density,
75 exchange_correlation_density_g);
77 std::vector<std::vector<Real>> exchange_correlation_potential_by_spin(
78 number_of_spin_components, std::vector<Real>(local_grid_points));
79 if (number_of_spin_components == 1) {
80 compute_xc_potential_unpolarized(exchange_correlation_density,
81 exchange_correlation_density_g,
83 exchange_correlation_potential_by_spin[0],
86 compute_xc_potential_spin_polarized(exchange_correlation_density,
87 exchange_correlation_density_g,
89 exchange_correlation_potential_by_spin[0],
90 exchange_correlation_potential_by_spin[1],
103 assemble_effective_potential(hartree_potential_real,
104 exchange_correlation_potential_by_spin,
105 number_of_spin_components,
106 local_ionic_potential_g,
117 std::unique_ptr<ExchangeCorrelationPotentialCalculator>
127 const std::vector<std::vector<Real>>& charge_density_real,
128 int number_of_spin_components,
129 std::vector<std::vector<Real>>& exchange_correlation_density,
130 std::vector<std::vector<Complex>>& exchange_correlation_density_g)
const {
134 exchange_correlation_density.assign(number_of_spin_components,
135 std::vector<Real>(local_grid_points));
136 exchange_correlation_density_g.assign(number_of_spin_components,
137 std::vector<Complex>(number_of_g_vectors));
139 for (
int spin_index = 0; spin_index < number_of_spin_components; ++spin_index) {
140 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
141 exchange_correlation_density[spin_index][grid_index] =
142 charge_density_real[spin_index][grid_index];
146 exchange_correlation_density_g[spin_index]);
155 Real two_pi_over_lattice_parameter_squared =
158 std::vector<Complex> hartree_potential_g(number_of_g_vectors,
Complex(0.0, 0.0));
159 Real hartree_energy_local = 0.0;
161 for (
int g_vector_index = first_nonzero_g_index; g_vector_index < number_of_g_vectors;
164 two_pi_over_lattice_parameter_squared;
167 hartree_potential_g[g_vector_index] =
173 Real gamma_factor = is_gamma_only ? 2.0 : 1.0;
174 hartree_energy_local +=
175 std::norm(output.
charge_density_g[g_vector_index]) * prefactor * gamma_factor;
179 std::vector<Real> hartree_potential_real;
181 return hartree_potential_real;
184 void compute_xc_potential_unpolarized(
185 const std::vector<std::vector<Real>>& exchange_correlation_density,
186 const std::vector<std::vector<Complex>>& exchange_correlation_density_g,
187 const std::vector<std::vector<Real>>& charge_density_real,
188 std::vector<Real>& exchange_correlation_potential,
189 EffectivePotentialResult& output)
const {
194 exchange_correlation_potential.assign(local_grid_points, 0.0);
195 std::vector<Real> exchange_correlation_energy_density(local_grid_points);
202 exchange_correlation_density[0],
203 exchange_correlation_density_g[0],
204 exchange_correlation_potential,
205 exchange_correlation_energy_density);
207 output.exchange_correlation_energy = 0.0;
208 output.exchange_correlation_potential_energy = 0.0;
209 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
210 output.exchange_correlation_energy += exchange_correlation_energy_density[grid_index] *
211 exchange_correlation_density[0][grid_index];
212 output.exchange_correlation_potential_energy +=
213 exchange_correlation_potential[grid_index] * charge_density_real[0][grid_index];
215 output.exchange_correlation_energy *= cell_volume / total_grid_points;
216 output.exchange_correlation_potential_energy *= cell_volume / total_grid_points;
219 void compute_xc_potential_spin_polarized(
220 const std::vector<std::vector<Real>>& exchange_correlation_density,
221 const std::vector<std::vector<Complex>>& exchange_correlation_density_g,
222 const std::vector<std::vector<Real>>& charge_density_real,
223 std::vector<Real>& exchange_correlation_potential_up,
224 std::vector<Real>& exchange_correlation_potential_down,
225 EffectivePotentialResult& output)
const {
230 exchange_correlation_potential_up.assign(local_grid_points, 0.0);
231 exchange_correlation_potential_down.assign(local_grid_points, 0.0);
232 std::vector<Real> exchange_correlation_energy_density(local_grid_points);
239 exchange_correlation_density[0],
240 exchange_correlation_density[1],
241 exchange_correlation_density_g[0],
242 exchange_correlation_density_g[1],
243 exchange_correlation_potential_up,
244 exchange_correlation_potential_down,
245 exchange_correlation_energy_density);
247 output.exchange_correlation_energy = 0.0;
248 output.exchange_correlation_potential_energy = 0.0;
249 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
250 Real total_density = exchange_correlation_density[0][grid_index] +
251 exchange_correlation_density[1][grid_index];
252 output.exchange_correlation_energy +=
253 exchange_correlation_energy_density[grid_index] * total_density;
254 output.exchange_correlation_potential_energy +=
255 exchange_correlation_potential_up[grid_index] * charge_density_real[0][grid_index] +
256 exchange_correlation_potential_down[grid_index] *
257 charge_density_real[1][grid_index];
259 output.exchange_correlation_energy *= cell_volume / total_grid_points;
260 output.exchange_correlation_potential_energy *= cell_volume / total_grid_points;
267 void assemble_effective_potential(
268 const std::vector<Real>& hartree_potential_real,
269 const std::vector<std::vector<Real>>& exchange_correlation_potential_by_spin,
270 int number_of_spin_components,
271 const std::vector<Complex>& local_ionic_potential_g,
272 EffectivePotentialResult& output)
const {
283 output.real_space_potential.resize(number_of_spin_components);
284 for (
int spin_index = 0; spin_index < number_of_spin_components; ++spin_index) {
285 output.real_space_potential[spin_index].resize(local_grid_points);
286 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
287 output.real_space_potential[spin_index][grid_index] =
288 hartree_potential_real[grid_index] +
289 exchange_correlation_potential_by_spin[spin_index][grid_index] +
290 local_potential_real_space[grid_index];
294 std::vector<Real> spin_averaged_potential(local_grid_points, 0.0);
295 for (
int spin_index = 0; spin_index < number_of_spin_components; ++spin_index) {
296 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
297 spin_averaged_potential[grid_index] +=
298 output.real_space_potential[spin_index][grid_index] / number_of_spin_components;
309 output.total_potential_g_by_spin.resize(number_of_spin_components);
310 for (
int spin_index = 0; spin_index < number_of_spin_components; ++spin_index) {
312 output.total_potential_g_by_spin[spin_index]);
315 std::vector<Real> exchange_correlation_potential_average(local_grid_points, 0.0);
316 for (
int grid_index = 0; grid_index < local_grid_points; ++grid_index) {
317 exchange_correlation_potential_average[grid_index] =
318 spin_averaged_potential[grid_index] - hartree_potential_real[grid_index] -
319 local_potential_real_space[grid_index];
322 output.exchange_correlation_potential_g);