130 extern __shared__ T shared_memory[];
131 const int number_of_tasks = dev_.num_tasks_per_block_dev[
block_index()];
133 if (number_of_tasks == 0)
136 T *smem_alpha = &shared_memory[0];
138 const int offset = dev_.sorted_blocks_offset_dev[
block_index()];
140 T *__restrict__ smem_cab = allocate_workspace<T>(dev_);
162 for (
int tk = 0; tk < number_of_tasks; tk++) {
164 const int task_id = dev_.task_sorted_by_blocks_dev[offset + tk];
165 if (dev_.tasks[task_id].skip_task)
169 T *__restrict__ coef_ =
170 &dev_.buffers_dev.coef[dev_.tasks[task_id].coef_offset];
177 for (
int i = tid / 8;
i < task.nsgf_setb;
i += 8) {
178 for (
int j = tid % 8; j < task.nsgf_seta; j += 8) {
181 if (task.block_transposed) {
183 task.pab_block[j * task.nsgfb +
i] * task.off_diag_twice;
186 task.pab_block[
i * task.nsgfa + j] * task.off_diag_twice;
188 for (
int jco = task.first_cosetb; jco < task.ncosetb; jco++) {
189 const T sphib = task.sphib[
i * task.maxcob + jco];
191 for (
int ico = task.first_coseta; ico < task.ncoseta; ico++) {
193 const T hab = get_hab<COMPUTE_TAU, T>(a, b, task.zeta, task.zetb,
195 T sphia_times_sphib = task.sphia[j * task.maxcoa + ico] * sphib;
196 tmp += hab * sphia_times_sphib;
198 sphia_times_sphib *= block_value;
199 fa[0] += sphia_times_sphib *
200 get_force_a<COMPUTE_TAU, T>(a, b, 0, task.zeta, task.zetb,
202 fa[1] += sphia_times_sphib *
203 get_force_a<COMPUTE_TAU, T>(a, b, 1, task.zeta, task.zetb,
205 fa[2] += sphia_times_sphib *
206 get_force_a<COMPUTE_TAU, T>(a, b, 2, task.zeta, task.zetb,
209 fb[0] += sphia_times_sphib *
210 get_force_b<COMPUTE_TAU, T>(a, b, 0, task.zeta, task.zetb,
211 task.rab, task.n1, smem_cab);
212 fb[1] += sphia_times_sphib *
213 get_force_b<COMPUTE_TAU, T>(a, b, 1, task.zeta, task.zetb,
214 task.rab, task.n1, smem_cab);
215 fb[2] += sphia_times_sphib *
216 get_force_b<COMPUTE_TAU, T>(a, b, 2, task.zeta, task.zetb,
217 task.rab, task.n1, smem_cab);
219 if (dev_.buffers_dev.virial !=
nullptr) {
222 (get_virial_a<COMPUTE_TAU, T>(a, b, 0, 0, task.zeta,
223 task.zetb, task.n1, smem_cab) +
224 get_virial_b<COMPUTE_TAU, T>(a, b, 0, 0, task.zeta,
225 task.zetb, task.rab, task.n1,
229 (get_virial_a<COMPUTE_TAU, T>(a, b, 0, 1, task.zeta,
230 task.zetb, task.n1, smem_cab) +
231 get_virial_b<COMPUTE_TAU, T>(a, b, 0, 1, task.zeta,
232 task.zetb, task.rab, task.n1,
236 (get_virial_a<COMPUTE_TAU, T>(a, b, 0, 2, task.zeta,
237 task.zetb, task.n1, smem_cab) +
238 get_virial_b<COMPUTE_TAU, T>(a, b, 0, 2, task.zeta,
239 task.zetb, task.rab, task.n1,
243 (get_virial_a<COMPUTE_TAU, T>(a, b, 1, 0, task.zeta,
244 task.zetb, task.n1, smem_cab) +
245 get_virial_b<COMPUTE_TAU, T>(a, b, 1, 0, task.zeta,
246 task.zetb, task.rab, task.n1,
250 (get_virial_a<COMPUTE_TAU, T>(a, b, 1, 1, task.zeta,
251 task.zetb, task.n1, smem_cab) +
252 get_virial_b<COMPUTE_TAU, T>(a, b, 1, 1, task.zeta,
253 task.zetb, task.rab, task.n1,
257 (get_virial_a<COMPUTE_TAU, T>(a, b, 1, 2, task.zeta,
258 task.zetb, task.n1, smem_cab) +
259 get_virial_b<COMPUTE_TAU, T>(a, b, 1, 2, task.zeta,
260 task.zetb, task.rab, task.n1,
264 (get_virial_a<COMPUTE_TAU, T>(a, b, 2, 0, task.zeta,
265 task.zetb, task.n1, smem_cab) +
266 get_virial_b<COMPUTE_TAU, T>(a, b, 2, 0, task.zeta,
267 task.zetb, task.rab, task.n1,
271 (get_virial_a<COMPUTE_TAU, T>(a, b, 2, 1, task.zeta,
272 task.zetb, task.n1, smem_cab) +
273 get_virial_b<COMPUTE_TAU, T>(a, b, 2, 1, task.zeta,
274 task.zetb, task.rab, task.n1,
278 (get_virial_a<COMPUTE_TAU, T>(a, b, 2, 2, task.zeta,
279 task.zetb, task.n1, smem_cab) +
280 get_virial_b<COMPUTE_TAU, T>(a, b, 2, 2, task.zeta,
281 task.zetb, task.rab, task.n1,
287 if (task.block_transposed) {
288 task.hab_block[j * task.nsgfb +
i] += tmp;
290 task.hab_block[
i * task.nsgfa + j] += tmp;
300 const int task_id = dev_.task_sorted_by_blocks_dev[offset];
301 const auto &glb_task = dev_.tasks[task_id];
302 const int iatom = glb_task.iatom;
303 const int jatom = glb_task.jatom;
304 T *forces_a = &dev_.buffers_dev.forces[3 * iatom];
305 T *forces_b = &dev_.buffers_dev.forces[3 * jatom];
307 T *sum = (T *)shared_memory;
308 if (dev_.buffers_dev.virial !=
nullptr) {
310 for (
int i = 0;
i < 9;
i++) {
311 virial[
i] = block_reduce_64<T>(sum, virial[
i], tid);
314 atomicAdd(dev_.buffers_dev.virial +
i, virial[
i]);
318 for (
int i = 0;
i < 3;
i++) {
319 fa[
i] = block_reduce_64<T>(sum, fa[
i], tid);
322 atomicAdd(forces_a +
i, fa[
i]);
324 fb[
i] = block_reduce_64<T>(sum, fb[
i], tid);
327 atomicAdd(forces_b +
i, fb[
i]);
361 if (dev_.tasks[dev_.first_task +
block_index()].skip_task)
373 dh_[tid] = dev_.dh_[tid];
379 setup_task_cube_center<T, T3, distributed__>(dev_, task);
383 __shared__ T accumulator[lbatch][64];
388 const short int size_loop =
389 (ncoset(task.lp) / lbatch + ((ncoset(task.lp) % lbatch) != 0)) * lbatch;
390 const short int length = ncoset(task.lp);
391 for (
int ico = 0; ico < size_loop; ico += lbatch) {
393 for (
int i = 0;
i < lbatch;
i++)
394 accumulator[
i][tid] = 0.0;
398 for (
int z = threadIdx.z; z < task.cube_size.z; z += blockDim.z) {
399 int z2 =
wrap_grid_index(z + task.cube_center.z, dev_.grid_full_size_.z);
403 if (task.apply_border_mask) {
405 if ((z2 < task.window_shift.z) || (z2 > task.window_size.z)) {
413 int ymax = task.cube_size.y - 1;
416 if (orthogonal_ && !task.apply_border_mask) {
420 for (
int y = ymin + threadIdx.y; y <= ymax; y += blockDim.y) {
426 if (task.apply_border_mask) {
427 if ((y2 < task.window_shift.y) || (y2 > task.window_size.y)) {
434 int xmax = task.cube_size.x - 1;
436 if (orthogonal_ && !task.apply_border_mask) {
437 calculate_xmin_xmax_boundaries<T, T3>(task, y, kremain, xmin, xmax);
440 for (
int x = xmin + threadIdx.x; x <= xmax; x += blockDim.x) {
446 if (task.apply_border_mask) {
447 if ((x2 < task.window_shift.x) || (x2 > task.window_size.x)) {
458 (y + task.lb_cube.y + task.roffset.y),
459 (z + task.lb_cube.z + task.roffset.z));
463 const T r3x2 = r3.x * r3.x;
464 const T r3y2 = r3.y * r3.y;
465 const T r3z2 = r3.z * r3.z;
472 if (((task.radius * task.radius) <= (r3x2 + r3y2 + r3z2)) &&
473 (!orthogonal_ || task.apply_border_mask))
477 if ((!orthogonal_) &&
478 ((task.radius * task.radius) <= (r3x2 + r3y2 + r3z2)))
486 const int grid_index =
487 (z2 * dev_.grid_local_size_.y + y2) * dev_.grid_local_size_.x +
489 T grid_value = __ldg(&dev_.buffers_dev.grid[grid_index]);
491 const T r3xy = r3.x * r3.y;
492 const T r3xz = r3.x * r3.z;
493 const T r3yz = r3.y * r3.z;
495 grid_value *= exp(-(r3x2 + r3y2 + r3z2) * task.zetp);
497 switch (ico / lbatch) {
499 accumulator[0][tid] += grid_value;
502 accumulator[1][tid] += grid_value * r3.x;
503 accumulator[2][tid] += grid_value * r3.y;
504 accumulator[3][tid] += grid_value * r3.z;
508 accumulator[4][tid] += grid_value * r3x2;
509 accumulator[5][tid] += grid_value * r3xy;
510 accumulator[6][tid] += grid_value * r3xz;
511 accumulator[7][tid] += grid_value * r3y2;
512 accumulator[8][tid] += grid_value * r3yz;
513 accumulator[9][tid] += grid_value * r3z2;
516 T tmp = grid_value * r3x2;
517 accumulator[10][tid] += tmp * r3.x;
518 accumulator[11][tid] += tmp * r3.y;
519 accumulator[12][tid] += tmp * r3.z;
520 tmp = grid_value * r3.x;
521 accumulator[13][tid] += tmp * r3y2;
522 accumulator[14][tid] += tmp * r3yz;
523 accumulator[15][tid] += tmp * r3z2;
524 tmp = grid_value * r3y2;
525 accumulator[16][tid] += tmp * r3.y;
526 accumulator[17][tid] += tmp * r3.z;
527 tmp = grid_value * r3z2;
528 accumulator[18][tid] += tmp * r3.y;
529 accumulator[19][tid] += tmp * r3.z;
534 T tmp = grid_value * r3x2;
535 accumulator[0][tid] += tmp * r3x2;
536 accumulator[1][tid] += tmp * r3xy;
537 accumulator[2][tid] += tmp * r3xz;
538 accumulator[3][tid] += tmp * r3y2;
539 accumulator[4][tid] += tmp * r3yz;
540 accumulator[5][tid] += tmp * r3z2;
541 tmp = grid_value * r3y2;
542 accumulator[6][tid] += tmp * r3xy;
543 accumulator[7][tid] += tmp * r3xz;
544 tmp = grid_value * r3z2;
545 accumulator[8][tid] += tmp * r3xy;
546 accumulator[9][tid] += tmp * r3xz;
549 T tmp = grid_value * r3y2;
550 accumulator[10][tid] += tmp * r3y2;
551 accumulator[11][tid] += tmp * r3yz;
552 accumulator[12][tid] += tmp * r3z2;
553 accumulator[13][tid] += grid_value * r3yz * r3z2;
554 accumulator[14][tid] += grid_value * r3z2 * r3z2;
557 T tmp = grid_value * r3x2 * r3x2;
558 accumulator[15][tid] += tmp * r3.x;
559 accumulator[16][tid] += tmp * r3.y;
560 accumulator[17][tid] += tmp * r3.z;
561 tmp = grid_value * r3x2;
562 accumulator[18][tid] += tmp * r3.x * r3y2;
563 accumulator[19][tid] += tmp * r3xy * r3.z;
567 T tmp = grid_value * r3x2;
568 accumulator[0][tid] += tmp * r3.x * r3z2;
569 accumulator[1][tid] += tmp * r3y2 * r3.y;
570 accumulator[2][tid] += tmp * r3y2 * r3.z;
571 accumulator[3][tid] += tmp * r3.y * r3z2;
572 accumulator[4][tid] += tmp * r3z2 * r3.z;
573 tmp = grid_value * r3.x * r3y2;
574 accumulator[5][tid] += tmp * r3y2;
575 accumulator[6][tid] += tmp * r3yz;
576 accumulator[7][tid] += tmp * r3z2;
577 tmp = grid_value * r3.x * r3z2;
578 accumulator[8][tid] += tmp * r3yz;
579 accumulator[9][tid] += tmp * r3z2;
580 tmp = grid_value * r3y2 * r3.y;
581 accumulator[10][tid] += tmp * r3y2;
582 accumulator[11][tid] += tmp * r3yz;
583 accumulator[12][tid] += tmp * r3z2;
584 accumulator[13][tid] += grid_value * r3y2 * r3z2 * r3.z;
585 accumulator[14][tid] += grid_value * r3.y * r3z2 * r3z2;
586 accumulator[15][tid] += grid_value * r3z2 * r3z2 * r3.z;
588 tmp = grid_value * r3x2 * r3x2;
589 accumulator[16][tid] += tmp * r3x2;
590 accumulator[17][tid] += tmp * r3xy;
591 accumulator[18][tid] += tmp * r3xz;
592 accumulator[19][tid] += tmp * r3y2;
596 T tmp = grid_value * r3x2;
597 accumulator[0][tid] += tmp * r3x2 * r3yz;
598 accumulator[1][tid] += tmp * r3x2 * r3z2;
599 accumulator[2][tid] += tmp * r3y2 * r3xy;
600 accumulator[3][tid] += tmp * r3y2 * r3xz;
601 accumulator[4][tid] += tmp * r3xy * r3z2;
602 accumulator[5][tid] += tmp * r3z2 * r3xz;
603 accumulator[6][tid] += tmp * r3y2 * r3y2;
604 accumulator[7][tid] += tmp * r3y2 * r3yz;
605 accumulator[8][tid] += tmp * r3y2 * r3z2;
606 accumulator[9][tid] += tmp * r3z2 * r3yz;
607 accumulator[10][tid] += tmp * r3z2 * r3z2;
608 tmp = grid_value * r3y2 * r3y2;
609 accumulator[11][tid] += tmp * r3xy;
610 accumulator[12][tid] += tmp * r3xz;
611 accumulator[13][tid] +=
612 grid_value * r3y2 * r3xy * r3z2;
613 accumulator[14][tid] +=
614 grid_value * r3y2 * r3z2 * r3xz;
615 accumulator[15][tid] += grid_value * r3xy * r3z2 * r3z2;
616 accumulator[16][tid] += grid_value * r3z2 * r3z2 * r3xz;
617 accumulator[17][tid] += tmp * r3y2;
618 accumulator[18][tid] += tmp * r3yz;
619 accumulator[19][tid] += tmp * r3z2;
622 for (
int ic = 0; (ic < lbatch) && ((ic + ico) < length); ic++) {
625 for (
int po = 0; po < (co.l[2] >> 1); po++)
629 for (
int po = 0; po < (co.l[1] >> 1); po++)
633 for (
int po = 0; po < (co.l[0] >> 1); po++)
637 accumulator[ic][tid] += tmp * grid_value;
645 const int max_i = min(length - ico, lbatch);
654 for (
int i = 0;
i < max_i;
i++) {
656 T val = accumulator[
i][tid] + accumulator[
i][tid + 32];
666 for (
int offset = 16; offset > 0; offset >>= 1) {
667#if defined(__CUDACC__)
668 val += __shfl_down_sync(0xffffffff, val, offset);
670 val += __shfl_down(val, offset);
675 accumulator[
i][0] = val;
677#if defined(__CUDACC__)
682#if !defined(__CUDACC__)
686 if (tid < min(length - ico, lbatch)) {
687 const size_t coef_offset =
688 dev_.tasks[dev_.first_task +
block_index()].coef_offset;
689 dev_.buffers_dev.coef[coef_offset + tid + ico] = accumulator[tid][0];