Loading...
Searching...
No Matches
gpu_kernels_sycl.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <sycl/sycl.hpp>
5
6namespace q3 {
7namespace diagonalizer {
8namespace planewave {
9namespace gpu {
10
11static sycl::queue get_sycl_queue() {
12 static sycl::queue queue{sycl::default_selector_v};
13 return queue;
14}
15
16void launch_apply_kinetic_energy(int number_of_vectors,
17 int number_of_plane_waves,
18 const double* kinetic_energy,
19 const std::complex<double>* psi,
20 std::complex<double>* hpsi) {
21 int total_elements = number_of_vectors * number_of_plane_waves;
22 if (total_elements == 0)
23 return;
24 auto queue = get_sycl_queue();
25 queue
26 .parallel_for(sycl::range<1>(total_elements),
27 [=](sycl::id<1> idx) {
28 int index = idx[0];
29 int g_index = index % number_of_plane_waves;
30 hpsi[index] = kinetic_energy[g_index] * psi[index];
31 })
32 .wait();
33}
34
35void launch_apply_kinetic_energy_single(int number_of_vectors,
36 int number_of_plane_waves,
37 const float* kinetic_energy,
38 const std::complex<float>* psi,
39 std::complex<float>* hpsi) {
40 int total_elements = number_of_vectors * number_of_plane_waves;
41 if (total_elements == 0)
42 return;
43 auto queue = get_sycl_queue();
44 queue
45 .parallel_for(sycl::range<1>(total_elements),
46 [=](sycl::id<1> idx) {
47 int index = idx[0];
48 int g_index = index % number_of_plane_waves;
49 hpsi[index] = kinetic_energy[g_index] * psi[index];
50 })
51 .wait();
52}
53
54void launch_scatter_g_to_fft_grid(int number_of_vectors,
55 int number_of_plane_waves,
56 int local_smooth_grid_points,
57 const int* g_to_fft_mapping,
58 const int* minus_g_to_fft_mapping,
59 bool is_gamma_only,
60 const std::complex<double>* psi,
61 std::complex<double>* fft_workspace) {
62 int total_elements = number_of_vectors * number_of_plane_waves;
63 if (total_elements == 0)
64 return;
65 auto queue = get_sycl_queue();
66 queue
67 .memset(fft_workspace,
68 0,
69 number_of_vectors * local_smooth_grid_points * sizeof(std::complex<double>))
70 .wait();
71 queue
72 .parallel_for(
73 sycl::range<1>(total_elements),
74 [=](sycl::id<1> idx) {
75 int index = idx[0];
76 int vector_index = index / number_of_plane_waves;
77 int g_index = index % number_of_plane_waves;
78 std::complex<double> val = psi[index];
79 int fft_index = g_to_fft_mapping[g_index];
80 if (fft_index >= 0) {
81 fft_workspace[vector_index * local_smooth_grid_points + fft_index] = val;
82 }
83 if (is_gamma_only && g_index > 0 && minus_g_to_fft_mapping != nullptr) {
84 int fft_minus = minus_g_to_fft_mapping[g_index];
85 if (fft_minus >= 0) {
86 fft_workspace[vector_index * local_smooth_grid_points + fft_minus] =
87 std::conj(val);
88 }
89 }
90 })
91 .wait();
92}
93
94void launch_scatter_g_to_fft_grid_single(int number_of_vectors,
95 int number_of_plane_waves,
96 int local_smooth_grid_points,
97 const int* g_to_fft_mapping,
98 const int* minus_g_to_fft_mapping,
99 bool is_gamma_only,
100 const std::complex<float>* psi,
101 std::complex<float>* fft_workspace) {
102 int total_elements = number_of_vectors * number_of_plane_waves;
103 if (total_elements == 0)
104 return;
105 auto queue = get_sycl_queue();
106 queue
107 .memset(fft_workspace,
108 0,
109 number_of_vectors * local_smooth_grid_points * sizeof(std::complex<float>))
110 .wait();
111 queue
112 .parallel_for(
113 sycl::range<1>(total_elements),
114 [=](sycl::id<1> idx) {
115 int index = idx[0];
116 int vector_index = index / number_of_plane_waves;
117 int g_index = index % number_of_plane_waves;
118 std::complex<float> val = psi[index];
119 int fft_index = g_to_fft_mapping[g_index];
120 if (fft_index >= 0) {
121 fft_workspace[vector_index * local_smooth_grid_points + fft_index] = val;
122 }
123 if (is_gamma_only && g_index > 0 && minus_g_to_fft_mapping != nullptr) {
124 int fft_minus = minus_g_to_fft_mapping[g_index];
125 if (fft_minus >= 0) {
126 fft_workspace[vector_index * local_smooth_grid_points + fft_minus] =
127 std::conj(val);
128 }
129 }
130 })
131 .wait();
132}
133
134void launch_scatter_g_to_fft_grid_mixed(int number_of_vectors,
135 int number_of_plane_waves,
136 int local_smooth_grid_points,
137 const int* g_to_fft_mapping,
138 const int* minus_g_to_fft_mapping,
139 bool is_gamma_only,
140 const std::complex<double>* psi,
141 std::complex<float>* fft_workspace) {
142 int total_elements = number_of_vectors * number_of_plane_waves;
143 if (total_elements == 0)
144 return;
145 auto queue = get_sycl_queue();
146 queue
147 .memset(fft_workspace,
148 0,
149 number_of_vectors * local_smooth_grid_points * sizeof(std::complex<float>))
150 .wait();
151 queue
152 .parallel_for(
153 sycl::range<1>(total_elements),
154 [=](sycl::id<1> idx) {
155 int index = idx[0];
156 int vector_index = index / number_of_plane_waves;
157 int g_index = index % number_of_plane_waves;
158 std::complex<double> val = psi[index];
159 std::complex<float> val_single(static_cast<float>(val.real()),
160 static_cast<float>(val.imag()));
161 int fft_index = g_to_fft_mapping[g_index];
162 if (fft_index >= 0) {
163 fft_workspace[vector_index * local_smooth_grid_points + fft_index] = val_single;
164 }
165 if (is_gamma_only && g_index > 0 && minus_g_to_fft_mapping != nullptr) {
166 int fft_minus = minus_g_to_fft_mapping[g_index];
167 if (fft_minus >= 0) {
168 fft_workspace[vector_index * local_smooth_grid_points + fft_minus] =
169 std::conj(val_single);
170 }
171 }
172 })
173 .wait();
174}
175
176void launch_multiply_potential(int number_of_vectors,
177 int local_smooth_grid_points,
178 const double* potential,
179 std::complex<double>* fft_workspace) {
180 int total_elements = number_of_vectors * local_smooth_grid_points;
181 if (total_elements == 0)
182 return;
183 auto queue = get_sycl_queue();
184 queue
185 .parallel_for(sycl::range<1>(total_elements),
186 [=](sycl::id<1> idx) {
187 int index = idx[0];
188 int grid_index = index % local_smooth_grid_points;
189 fft_workspace[index] *= potential[grid_index];
190 })
191 .wait();
192}
193
194void launch_multiply_potential_single(int number_of_vectors,
195 int local_smooth_grid_points,
196 const float* potential,
197 std::complex<float>* fft_workspace) {
198 int total_elements = number_of_vectors * local_smooth_grid_points;
199 if (total_elements == 0)
200 return;
201 auto queue = get_sycl_queue();
202 queue
203 .parallel_for(sycl::range<1>(total_elements),
204 [=](sycl::id<1> idx) {
205 int index = idx[0];
206 int grid_index = index % local_smooth_grid_points;
207 fft_workspace[index] *= potential[grid_index];
208 })
209 .wait();
210}
211
212void launch_gather_fft_grid_to_g(int number_of_vectors,
213 int number_of_plane_waves,
214 int local_smooth_grid_points,
215 const int* g_to_fft_mapping,
216 const std::complex<double>* fft_workspace,
217 std::complex<double>* hpsi) {
218 int total_elements = number_of_vectors * number_of_plane_waves;
219 if (total_elements == 0)
220 return;
221 auto queue = get_sycl_queue();
222 queue
223 .parallel_for(
224 sycl::range<1>(total_elements),
225 [=](sycl::id<1> idx) {
226 int index = idx[0];
227 int vector_index = index / number_of_plane_waves;
228 int g_index = index % number_of_plane_waves;
229 int fft_index = g_to_fft_mapping[g_index];
230 if (fft_index >= 0) {
231 hpsi[index] +=
232 fft_workspace[vector_index * local_smooth_grid_points + fft_index];
233 }
234 })
235 .wait();
236}
237
238void launch_gather_fft_grid_to_g_single(int number_of_vectors,
239 int number_of_plane_waves,
240 int local_smooth_grid_points,
241 const int* g_to_fft_mapping,
242 const std::complex<float>* fft_workspace,
243 std::complex<float>* hpsi) {
244 int total_elements = number_of_vectors * number_of_plane_waves;
245 if (total_elements == 0)
246 return;
247 auto queue = get_sycl_queue();
248 queue
249 .parallel_for(
250 sycl::range<1>(total_elements),
251 [=](sycl::id<1> idx) {
252 int index = idx[0];
253 int vector_index = index / number_of_plane_waves;
254 int g_index = index % number_of_plane_waves;
255 int fft_index = g_to_fft_mapping[g_index];
256 if (fft_index >= 0) {
257 hpsi[index] +=
258 fft_workspace[vector_index * local_smooth_grid_points + fft_index];
259 }
260 })
261 .wait();
262}
263
264void launch_gather_fft_grid_to_g_mixed(int number_of_vectors,
265 int number_of_plane_waves,
266 int local_smooth_grid_points,
267 const int* g_to_fft_mapping,
268 const std::complex<float>* fft_workspace,
269 std::complex<double>* hpsi) {
270 int total_elements = number_of_vectors * number_of_plane_waves;
271 if (total_elements == 0)
272 return;
273 auto queue = get_sycl_queue();
274 queue
275 .parallel_for(
276 sycl::range<1>(total_elements),
277 [=](sycl::id<1> idx) {
278 int index = idx[0];
279 int vector_index = index / number_of_plane_waves;
280 int g_index = index % number_of_plane_waves;
281 int fft_index = g_to_fft_mapping[g_index];
282 if (fft_index >= 0) {
283 std::complex<float> val =
284 fft_workspace[vector_index * local_smooth_grid_points + fft_index];
285 hpsi[index] += std::complex<double>(static_cast<double>(val.real()),
286 static_cast<double>(val.imag()));
287 }
288 })
289 .wait();
290}
291
292void launch_compute_residuals(int number_of_bands,
293 int number_of_plane_waves,
294 const double* eigenvalues,
295 const std::complex<double>* hamiltonian_ritz_vectors,
296 const std::complex<double>* overlap_ritz_vectors,
297 std::complex<double>* residual_wavefunctions) {
298 int total_elements = number_of_bands * number_of_plane_waves;
299 if (total_elements == 0)
300 return;
301 auto queue = get_sycl_queue();
302 queue
303 .parallel_for(sycl::range<1>(total_elements),
304 [=](sycl::id<1> idx) {
305 int index = idx[0];
306 int band_index = index / number_of_plane_waves;
307 residual_wavefunctions[index] =
308 hamiltonian_ritz_vectors[index] -
309 eigenvalues[band_index] * overlap_ritz_vectors[index];
310 })
311 .wait();
312}
313
314void launch_apply_preconditioner(int number_of_bands,
315 int number_of_plane_waves,
316 const double* kinetic_energy_squared,
317 const double* eigenvalues,
318 const bool* band_converged,
319 double floor_value,
320 std::complex<double>* residual_wavefunctions) {
321 int total_elements = number_of_bands * number_of_plane_waves;
322 if (total_elements == 0)
323 return;
324 auto queue = get_sycl_queue();
325 queue
326 .parallel_for(
327 sycl::range<1>(total_elements),
328 [=](sycl::id<1> idx) {
329 int index = idx[0];
330 int band_index = index / number_of_plane_waves;
331 if (band_converged[band_index]) {
332 return;
333 }
334 int g_index = index % number_of_plane_waves;
335 double value_x = kinetic_energy_squared[g_index] - eigenvalues[band_index];
336 double denominator =
337 0.5 * (1.0 + value_x + std::sqrt(1.0 + (value_x - 1.0) * (value_x - 1.0)));
338 if (denominator < floor_value) {
339 denominator = floor_value;
340 }
341 residual_wavefunctions[index] /= denominator;
342 })
343 .wait();
344}
345
346} // namespace gpu
347} // namespace planewave
348} // namespace diagonalizer
349} // namespace q3
void launch_apply_preconditioner(int number_of_bands, int number_of_plane_waves, const double *kinetic_energy_squared, const double *eigenvalues, const bool *band_converged, double floor_value, std::complex< double > *residual_wavefunctions)
void launch_apply_kinetic_energy_single(int number_of_vectors, int number_of_plane_waves, const float *kinetic_energy, const std::complex< float > *psi, std::complex< float > *hpsi)
void launch_gather_fft_grid_to_g_single(int number_of_vectors, int number_of_plane_waves, int local_smooth_grid_points, const int *g_to_fft_mapping, const std::complex< float > *fft_workspace, std::complex< float > *hpsi)
void launch_apply_kinetic_energy(int number_of_vectors, int number_of_plane_waves, const double *kinetic_energy, const std::complex< double > *psi, std::complex< double > *hpsi)
void launch_multiply_potential(int number_of_vectors, int local_smooth_grid_points, const double *potential, std::complex< double > *fft_workspace)
void launch_multiply_potential_single(int number_of_vectors, int local_smooth_grid_points, const float *potential, std::complex< float > *fft_workspace)
void launch_gather_fft_grid_to_g_mixed(int number_of_vectors, int number_of_plane_waves, int local_smooth_grid_points, const int *g_to_fft_mapping, const std::complex< float > *fft_workspace, std::complex< double > *hpsi)
void launch_scatter_g_to_fft_grid(int number_of_vectors, int number_of_plane_waves, int local_smooth_grid_points, const int *g_to_fft_mapping, const int *minus_g_to_fft_mapping, bool is_gamma_only, const std::complex< double > *psi, std::complex< double > *fft_workspace)
void launch_gather_fft_grid_to_g(int number_of_vectors, int number_of_plane_waves, int local_smooth_grid_points, const int *g_to_fft_mapping, const std::complex< double > *fft_workspace, std::complex< double > *hpsi)
void launch_compute_residuals(int number_of_bands, int number_of_plane_waves, const double *eigenvalues, const std::complex< double > *hamiltonian_ritz_vectors, const std::complex< double > *overlap_ritz_vectors, std::complex< double > *residual_wavefunctions)
void launch_scatter_g_to_fft_grid_mixed(int number_of_vectors, int number_of_plane_waves, int local_smooth_grid_points, const int *g_to_fft_mapping, const int *minus_g_to_fft_mapping, bool is_gamma_only, const std::complex< double > *psi, std::complex< float > *fft_workspace)
void launch_scatter_g_to_fft_grid_single(int number_of_vectors, int number_of_plane_waves, int local_smooth_grid_points, const int *g_to_fft_mapping, const int *minus_g_to_fft_mapping, bool is_gamma_only, const std::complex< float > *psi, std::complex< float > *fft_workspace)