Loading...
Searching...
No Matches
charge_density_transformer.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4
5/**
6 * ChargeDensityTransformer — G ↔ real-space transforms for charge density.
7 */
8
9#include <vector>
10
14
15namespace q3 {
16
18 public:
19 static void rho_g_to_r(const GVectorsGrid& g_vectors_grid,
20 const FFTGrid& fft_rho,
21 const std::vector<Complex>& charge_density_g_space,
22 std::vector<Real>& charge_density_real_space) {
23 int local_points = fft_rho.local_grid_points();
24 /**
25 * Reciprocal space goes in, real space comes out, and under the stick
26 * layout the two counts differ: size for the larger.
27 */
28 std::vector<Complex> work(
29 static_cast<std::size_t>(std::max(local_points, fft_rho.local_g_space_points())),
30 Complex(0.0, 0.0));
31
32 const auto& g_vectors = g_vectors_grid.g_vectors();
33 bool is_gamma_only = g_vectors_grid.is_gamma_only();
34
35 for (int g_vector_index = 0; g_vector_index < g_vectors_grid.number_of_g_vectors();
36 g_vector_index++) {
37 const auto& g_vector = g_vectors[g_vector_index];
38 int fft_index = fft_rho.g_vector_to_fft_grid_index(
39 g_vector.miller[0], g_vector.miller[1], g_vector.miller[2]);
40 if (fft_index >= 0) {
41 work[fft_index] = charge_density_g_space[g_vector_index];
42 }
43
44 // For gamma-only half-sphere: also set the -G position with conjugate.
45 if (is_gamma_only && g_vector_index >= g_vectors_grid.first_nonzero_g_index()) {
46 int minus_g_fft_index = fft_rho.g_vector_to_fft_grid_index(
47 -g_vector.miller[0], -g_vector.miller[1], -g_vector.miller[2]);
48 if (minus_g_fft_index >= 0) {
49 work[minus_g_fft_index] = std::conj(charge_density_g_space[g_vector_index]);
50 }
51 }
52 }
53
54 fft_rho.inverse(work.data());
55
56 charge_density_real_space.resize(local_points);
57 int total_grid_points = fft_rho.total_grid_points();
58 for (int grid_index = 0; grid_index < local_points; grid_index++) {
59 charge_density_real_space[grid_index] = work[grid_index].real() * total_grid_points;
60 }
61 }
62
63 static void rho_r_to_g(const GVectorsGrid& g_vectors_grid,
64 const FFTGrid& fft_rho,
65 const std::vector<Real>& charge_density_real_space,
66 std::vector<Complex>& charge_density_g_space) {
67 int local_points = fft_rho.local_grid_points();
68 std::vector<Complex> work(
69 static_cast<std::size_t>(std::max(local_points, fft_rho.local_g_space_points())),
70 Complex(0.0, 0.0));
71 for (int grid_index = 0; grid_index < local_points; grid_index++) {
72 work[grid_index] = Complex(charge_density_real_space[grid_index], 0.0);
73 }
74
75 fft_rho.forward(work.data());
76
77 Real inverse_grid_size = 1.0 / fft_rho.total_grid_points();
78 const auto& g_vectors = g_vectors_grid.g_vectors();
79 int number_of_g_vectors = g_vectors_grid.number_of_g_vectors();
80 charge_density_g_space.assign(number_of_g_vectors, Complex(0.0, 0.0));
81 for (int g_vector_index = 0; g_vector_index < number_of_g_vectors; g_vector_index++) {
82 const auto& g_vector = g_vectors[g_vector_index];
83 int fft_index = fft_rho.g_vector_to_fft_grid_index(
84 g_vector.miller[0], g_vector.miller[1], g_vector.miller[2]);
85 if (fft_index >= 0) {
86 charge_density_g_space[g_vector_index] = work[fft_index] * inverse_grid_size;
87 }
88 }
89
90 // Make G-space redundant
91 fft_rho.reduce_g_space(charge_density_g_space.data(), number_of_g_vectors);
92 }
93};
94
95} // namespace q3
static void rho_r_to_g(const GVectorsGrid &g_vectors_grid, const FFTGrid &fft_rho, const std::vector< Real > &charge_density_real_space, std::vector< Complex > &charge_density_g_space)
static void rho_g_to_r(const GVectorsGrid &g_vectors_grid, const FFTGrid &fft_rho, const std::vector< Complex > &charge_density_g_space, std::vector< Real > &charge_density_real_space)
virtual int g_vector_to_fft_grid_index(int miller_1, int miller_2, int miller_3) const =0
virtual int local_g_space_points() const
Definition fft_grid.hpp:88
virtual void reduce_g_space(Complex *data, int number_of_elements) const =0
virtual void forward(Complex *data) const =0
virtual int total_grid_points() const =0
virtual void inverse(Complex *data) const =0
virtual int local_grid_points() const =0
const std::vector< GVector > & g_vectors() const
int number_of_g_vectors() const
int first_nonzero_g_index() const
bool is_gamma_only() const
double Real
std::complex< double > Complex