15#if defined(__AVX2__) && defined(__FMA__)
23#define GRID_MAX_LP_OPTIMIZED 9
25#if (GRID_DO_COLLOCATE)
26#define GRID_CONST_WHEN_COLLOCATE const
27#define GRID_CONST_WHEN_INTEGRATE
29#define GRID_CONST_WHEN_COLLOCATE
30#define GRID_CONST_WHEN_INTEGRATE const
38ortho_cx_to_grid_scalar(const
int lp, const
int cmax, const
int i,
39 const
double pol[3][lp + 1][2 *
cmax + 1],
46#if (GRID_DO_COLLOCATE)
48 double reg[4] = {0.0, 0.0, 0.0, 0.0};
49#pragma omp simd reduction(+ : reg)
50 for (
int lxp = 0; lxp <= lp; lxp++) {
51 const double p =
pol[0][lxp][
i +
cmax];
52 reg[0] +=
cx[lxp * 4 + 0] * p;
53 reg[1] +=
cx[lxp * 4 + 1] * p;
54 reg[2] +=
cx[lxp * 4 + 2] * p;
55 reg[3] +=
cx[lxp * 4 + 3] * p;
66 for (
int lxp = 0; lxp <= lp; lxp++) {
67 const double p =
pol[0][lxp][
i +
cmax];
68 cx[lxp * 4 + 0] += reg[0] * p;
69 cx[lxp * 4 + 1] += reg[1] * p;
70 cx[lxp * 4 + 2] += reg[2] * p;
71 cx[lxp * 4 + 3] += reg[3] * p;
81#if defined(__AVX2__) && defined(__FMA__)
83ortho_cx_to_grid_avx2(
const int lp,
const int cmax,
const int i,
84 const double pol[3][lp + 1][2 *
cmax + 1],
91 const int icmax =
i +
cmax;
93#if (GRID_DO_COLLOCATE)
96 __m256d p_vec = _mm256_loadu_pd(&
pol[0][0][icmax]);
97 __m256d r_vec_0 = _mm256_mul_pd(p_vec, _mm256_set1_pd(
cx[0]));
98 __m256d r_vec_1 = _mm256_mul_pd(p_vec, _mm256_set1_pd(
cx[1]));
99 __m256d r_vec_2 = _mm256_mul_pd(p_vec, _mm256_set1_pd(
cx[2]));
100 __m256d r_vec_3 = _mm256_mul_pd(p_vec, _mm256_set1_pd(
cx[3]));
104 for (
int lxp = 1; lxp <= lp; lxp++) {
105 const double *cx_base = &
cx[lxp * 4];
106 p_vec = _mm256_loadu_pd(&
pol[0][lxp][icmax]);
107 r_vec_0 = _mm256_fmadd_pd(p_vec, _mm256_set1_pd(cx_base[0]), r_vec_0);
108 r_vec_1 = _mm256_fmadd_pd(p_vec, _mm256_set1_pd(cx_base[1]), r_vec_1);
109 r_vec_2 = _mm256_fmadd_pd(p_vec, _mm256_set1_pd(cx_base[2]), r_vec_2);
110 r_vec_3 = _mm256_fmadd_pd(p_vec, _mm256_set1_pd(cx_base[3]), r_vec_3);
114 _mm256_storeu_pd(
grid_0, _mm256_add_pd(_mm256_loadu_pd(
grid_0), r_vec_0));
115 _mm256_storeu_pd(
grid_1, _mm256_add_pd(_mm256_loadu_pd(
grid_1), r_vec_1));
116 _mm256_storeu_pd(
grid_2, _mm256_add_pd(_mm256_loadu_pd(
grid_2), r_vec_2));
117 _mm256_storeu_pd(
grid_3, _mm256_add_pd(_mm256_loadu_pd(
grid_3), r_vec_3));
121 __m256d grid_vec_0 = _mm256_loadu_pd(
grid_0);
122 __m256d grid_vec_1 = _mm256_loadu_pd(
grid_1);
123 __m256d grid_vec_2 = _mm256_loadu_pd(
grid_2);
124 __m256d grid_vec_3 = _mm256_loadu_pd(
grid_3);
127 for (
int lxp = 0; lxp <= lp; lxp++) {
128 __m256d p_vec = _mm256_loadu_pd(&
pol[0][lxp][icmax]);
131 __m256d xy0 = _mm256_mul_pd(p_vec, grid_vec_0);
132 __m256d xy1 = _mm256_mul_pd(p_vec, grid_vec_1);
133 __m256d xy2 = _mm256_mul_pd(p_vec, grid_vec_2);
134 __m256d xy3 = _mm256_mul_pd(p_vec, grid_vec_3);
137 __m256d temp01 = _mm256_hadd_pd(xy0, xy1);
140 __m256d temp23 = _mm256_hadd_pd(xy2, xy3);
143 __m256d swapped = _mm256_permute2f128_pd(temp01, temp23, 0x21);
146 __m256d blended = _mm256_blend_pd(temp01, temp23, 0b1100);
148 __m256d r_vec = _mm256_add_pd(swapped, blended);
151 double *cx_base = &
cx[lxp * 4];
152 _mm256_storeu_pd(cx_base, _mm256_add_pd(r_vec, _mm256_loadu_pd(cx_base)));
165 const
double pol[3][lp + 1][2 *
cmax + 1],
172 const int lb = *((*sphere_bounds_iter)++);
173 const int ub = 1 - lb;
178 for (
int istart = lb; istart <=
ub; istart++) {
180 const int cube2grid =
map[0][istart +
cmax] - istart;
193#if defined(__AVX2__) && defined(__FMA__)
194 const int istop_vec = istart + 4 * ((istop - istart + 1) / 4) - 1;
195 for (
int i = istart;
i <= istop_vec;
i += 4) {
196 const int ig =
i + cube2grid;
197 ortho_cx_to_grid_avx2(lp,
cmax,
i,
pol,
cx, &grid_base_0[ig],
198 &grid_base_1[ig], &grid_base_2[ig],
201 istart = istop_vec + 1;
205 for (
int i = istart;
i <= istop;
i++) {
206 const int ig =
i + cube2grid;
207 ortho_cx_to_grid_scalar(lp,
cmax,
i,
pol,
cx, &grid_base_0[ig],
208 &grid_base_1[ig], &grid_base_2[ig],
221 const
double pol[3][lp + 1][2 *
cmax + 1],
225 for (
int lyp = 0; lyp <= lp; lyp++) {
226 for (
int lxp = 0; lxp <= lp - lyp; lxp++) {
227 const double p1 =
pol[1][lyp][
j1 +
cmax];
228 const double p2 =
pol[1][lyp][
j2 +
cmax];
229 const int cxy_index = lyp * (lp + 1) * 2 + lxp * 2;
231#if (GRID_DO_COLLOCATE)
233 cx[lxp * 4 + 0] +=
cxy[cxy_index + 0] * p1;
234 cx[lxp * 4 + 1] +=
cxy[cxy_index + 1] * p1;
235 cx[lxp * 4 + 2] +=
cxy[cxy_index + 0] * p2;
236 cx[lxp * 4 + 3] +=
cxy[cxy_index + 1] * p2;
239 cxy[cxy_index + 0] +=
cx[lxp * 4 + 0] * p1;
240 cxy[cxy_index + 1] +=
cx[lxp * 4 + 1] * p1;
241 cxy[cxy_index + 0] +=
cx[lxp * 4 + 2] * p2;
242 cxy[cxy_index + 1] +=
cx[lxp * 4 + 3] * p2;
252static inline void __attribute__((always_inline)) ortho_cxy_to_grid_low(
253 const int lp,
const int j1,
const int j2,
const int kg1,
const int kg2,
255 const double pol[3][lp + 1][2 *
cmax + 1],
const int map[3][2 *
cmax + 1],
260#if (GRID_DO_COLLOCATE)
263 ortho_cx_to_grid(lp,
kg1,
kg2,
jg1,
jg2,
cmax,
pol,
map,
sections,
npts_local,
267 ortho_cx_to_grid(lp,
kg1,
kg2,
jg1,
jg2,
cmax,
pol,
map,
sections,
npts_local,
278 const int lp,
const int kg1,
const int kg2,
const int cmax,
279 const double pol[3][lp + 1][2 *
cmax + 1],
const int map[3][2 *
cmax + 1],
289 const int jstart = *((*sphere_bounds_iter)++);
290 const size_t cx_size = (lp + 1) * 4;
292 for (
int j1 = jstart;
j1 <= 0;
j1++) {
293 const int j2 = 1 -
j1;
297 memset(
cx, 0, cx_size *
sizeof(
double));
304 ortho_cxy_to_grid_low(ilp,
j1,
j2,
kg1,
kg2,
jg1,
jg2,
cmax,
pol,
map,
310 ortho_cxy_to_grid_low(lp,
j1,
j2,
kg1,
kg2,
jg1,
jg2,
cmax,
pol,
map,
323 const double pol[3][lp + 1][2 *
cmax + 1],
327 for (
int lzp = 0; lzp <= lp; lzp++) {
328 for (
int lyp = 0; lyp <= lp - lzp; lyp++) {
329 for (
int lxp = 0; lxp <= lp - lzp - lyp; lxp++) {
330 const double p1 =
pol[2][lzp][k1 +
cmax];
331 const double p2 =
pol[2][lzp][k2 +
cmax];
332 const int cxyz_index =
333 lzp * (lp + 1) * (lp + 1) + lyp * (lp + 1) + lxp;
334 const int cxy_index = lyp * (lp + 1) * 2 + lxp * 2;
336#if (GRID_DO_COLLOCATE)
338 cxy[cxy_index + 0] += cxyz[cxyz_index] * p1;
339 cxy[cxy_index + 1] += cxyz[cxyz_index] * p2;
342 cxyz[cxyz_index] +=
cxy[cxy_index + 0] * p1;
343 cxyz[cxyz_index] +=
cxy[cxy_index + 1] * p2;
356 const double dh_inv[3][3],
const double rp[3],
357 const int npts_global[3],
const int npts_local[3],
358 const int shift_local[3],
const double radius,
372 for (
int i = 0;
i < 3;
i++) {
373 double dh_inv_rp = 0.0;
374 for (
int j = 0; j < 3; j++) {
375 dh_inv_rp += dh_inv[j][
i] * rp[j];
377 cubecenter[
i] = (int)floor(dh_inv_rp);
381 for (
int i = 0;
i < 3;
i++) {
382 roffset[
i] = rp[
i] - ((double)cubecenter[
i]) * dh[
i][
i];
392 int lb_cube[3], ub_cube[3];
393 for (
int i = 0;
i < 3;
i++) {
394 lb_cube[
i] = (int)ceil(-1e-8 - disr_radius * dh_inv[
i][
i]);
395 ub_cube[
i] = 1 - lb_cube[
i];
399 modulo(cubecenter[
i] + lb_cube[
i] - shift_local[
i], npts_global[
i]) -
402 assert(offset + lb_cube[
i] >= 0);
407 const int cmax =
imax(
imax(ub_cube[0], ub_cube[1]), ub_cube[2]);
410 double pol_mutable[3][lp + 1][2 *
cmax + 1];
411 for (
int idir = 0; idir < 3; idir++) {
412 const double dr = dh[idir][idir];
413 const double ro = roffset[idir];
417 const double t_exp_1 = exp(-zetp * pow(dr, 2));
418 const double t_exp_2 = pow(t_exp_1, 2);
419 double t_exp_min_1 = exp(-zetp * pow(+dr - ro, 2));
420 double t_exp_min_2 = exp(-2 * zetp * (+dr - ro) * (-dr));
421 for (
int ig = 0; ig >= lb_cube[idir]; ig--) {
422 const double rpg = ig * dr - ro;
423 t_exp_min_1 *= t_exp_min_2 * t_exp_1;
424 t_exp_min_2 *= t_exp_2;
425 double pg = t_exp_min_1;
426 for (
int icoef = 0; icoef <= lp; icoef++) {
427 pol_mutable[idir][icoef][ig +
cmax] = pg;
431 double t_exp_plus_1 = exp(-zetp * pow(-ro, 2));
432 double t_exp_plus_2 = exp(-2 * zetp * (-ro) * (+dr));
433 for (
int ig = 0; ig >= lb_cube[idir]; ig--) {
434 const double rpg = (1 - ig) * dr - ro;
435 t_exp_plus_1 *= t_exp_plus_2 * t_exp_1;
436 t_exp_plus_2 *= t_exp_2;
437 double pg = t_exp_plus_1;
438 for (
int icoef = 0; icoef <= lp; icoef++) {
439 pol_mutable[idir][icoef][1 - ig +
cmax] = pg;
444 const double (*
pol)[lp + 1][2 *
cmax + 1] =
445 (
const double (*)[lp + 1][2 *
cmax + 1]) pol_mutable;
448 int map_mutable[3][2 *
cmax + 1];
449 for (
int i = 0;
i < 3;
i++) {
450 for (
int k = -
cmax; k <= +
cmax; k++) {
451 map_mutable[
i][k +
cmax] =
452 modulo(cubecenter[
i] + k - shift_local[
i], npts_global[
i]);
455 const int (*
map)[2 *
cmax + 1] = (
const int (*)[2 *
cmax + 1]) map_mutable;
458 int sections_mutable[3][2 *
cmax + 1];
459 for (
int i = 0;
i < 3;
i++) {
460 for (
int kg = 2 *
cmax; kg >= 0; kg--) {
461 if (kg == 2 *
cmax ||
map[
i][kg] !=
map[
i][kg + 1] - 1) {
462 sections_mutable[
i][kg] = 0;
464 sections_mutable[
i][kg] = sections_mutable[
i][kg + 1] + 1;
469 (
const int (*)[2 *
cmax + 1]) sections_mutable;
472 const int kstart = *((*sphere_bounds_iter)++);
473 const size_t cxy_size = (lp + 1) * (lp + 1) * 2;
474 double cxy[cxy_size];
475 for (
int k1 = kstart; k1 <= 0; k1++) {
476 const int k2 = 1 - k1;
480 memset(
cxy, 0, cxy_size *
sizeof(
double));
482#if (GRID_DO_COLLOCATE)
501 const int lp,
const int jg,
const int kg,
const int ismin,
const int ismax,
502 const int npts_local[3],
const int index_min[3],
const int index_max[3],
503 const int map_i[],
const int sections_i[],
const double gp[3],
const int k,
504 const int j,
const double exp_ij[],
const double exp_jk[],
509 const int stride_i = index_max[0] - index_min[0] + 1;
510 const int stride_j = index_max[1] - index_min[1] + 1;
511 const int idx_jk = (k - index_min[2]) * stride_j + j - index_min[1];
513#if defined(__AVX2__) && defined(__FMA__)
514 const __m256d v_gp0 = _mm256_set1_pd(gp[0]);
515 const __m256d v_four = _mm256_set1_pd(4.0);
516 const __m256d v_ejk = _mm256_set1_pd(exp_jk[idx_jk]);
517 __m256d v_ci[lp + 1];
519 for (
int il = 0; il <= lp; il++) {
520#if (GRID_DO_COLLOCATE)
521 v_ci[il] = _mm256_set1_pd(ci[il]);
523 v_ci[il] = _mm256_setzero_pd();
531 for (
int istart = ismin; istart <= ismax; istart++) {
532 const int istop =
imin(ismax, istart + sections_i[istart - index_min[0]]);
533 if (map_i[istart - index_min[0]] < 0) {
538 const int cube2grid = map_i[istart - index_min[0]] - istart;
540#if defined(__AVX2__) && defined(__FMA__)
541 const int istart_tail = istart + ((istop - istart + 1) / 4) * 4;
542 __m256d v_i = _mm256_set_pd(istart + 3, istart + 2, istart + 1, istart);
543 for (
int i = istart;
i < istart_tail;
i += 4) {
544 const int idx_ij = (j - index_min[1]) * stride_i +
i - index_min[0];
545 const int idx_ik = (k - index_min[2]) * stride_i +
i - index_min[0];
547 const __m256d v_di = _mm256_sub_pd(v_i, v_gp0);
548 v_i = _mm256_add_pd(v_i, v_four);
549 const __m256d v_eij = _mm256_loadu_pd(&
exp_ij[idx_ij]);
550 const __m256d v_eik = _mm256_loadu_pd(&exp_ik[idx_ik]);
551 __m256d v_dip = _mm256_mul_pd(_mm256_mul_pd(v_eij, v_ejk), v_eik);
553 const int grid_index = base +
i + cube2grid;
554#if (GRID_DO_COLLOCATE)
555 __m256d v_reg = _mm256_mul_pd(v_ci[0], v_dip);
557 for (
int il = 1; il <= lp; il++) {
558 v_dip = _mm256_mul_pd(v_dip, v_di);
559 v_reg = _mm256_fmadd_pd(v_ci[il], v_dip, v_reg);
561 __m256d v_grid = _mm256_loadu_pd(&
grid[grid_index]);
562 _mm256_storeu_pd(&
grid[grid_index], _mm256_add_pd(v_grid, v_reg));
564 const __m256d v_reg = _mm256_loadu_pd(&
grid[grid_index]);
565 v_ci[0] = _mm256_fmadd_pd(v_reg, v_dip, v_ci[0]);
567 for (
int il = 1; il <= lp; il++) {
568 v_dip = _mm256_mul_pd(v_dip, v_di);
569 v_ci[il] = _mm256_fmadd_pd(v_reg, v_dip, v_ci[il]);
574 const int istart_tail = istart;
577 for (
int i = istart_tail;
i <= istop;
i++) {
578 const int ig =
i + cube2grid;
579 const double di =
i - gp[0];
581 const int idx_ij = (j - index_min[1]) * stride_i +
i - index_min[0];
582 const int idx_ik = (k - index_min[2]) * stride_i +
i - index_min[0];
595 const double gaussian =
exp_ij[idx_ij] * exp_jk[idx_jk] * exp_ik[idx_ik];
597 const int grid_index = base + ig;
600#if (GRID_DO_COLLOCATE)
603 for (
int il = 0; il <= lp; il++) {
607 grid[grid_index] += reg;
610 const double reg =
grid[grid_index];
611 for (
int il = 0; il <= lp; il++) {
620#if defined(__AVX2__) && defined(__FMA__) && (!GRID_DO_COLLOCATE)
622 for (
int il = 0; il <= lp; il++) {
623 __m128d v_low = _mm256_castpd256_pd128(v_ci[il]);
624 __m128d v_high = _mm256_extractf128_pd(v_ci[il], 1);
625 __m128d v_sum2 = _mm_add_pd(v_low, v_high);
626 __m128d v_shuf = _mm_unpackhi_pd(v_sum2, v_sum2);
627 ci[il] += _mm_cvtsd_f64(_mm_add_sd(v_sum2, v_shuf));
641 for (
int jl = 0; jl <= lp; jl++) {
642 for (
int il = 0; il <= lp - jl; il++) {
643 const int cij_index = jl * (lp + 1) + il;
644#if (GRID_DO_COLLOCATE)
645 ci[il] += cij[cij_index] * djp;
647 cij[cij_index] += ci[il] * djp;
658static inline void __attribute__((always_inline)) general_cij_to_grid_low(
659 const int lp,
const int jg,
const int kg,
const int ismin,
const int ismax,
660 const int npts_local[3],
const int index_min[3],
const int index_max[3],
661 const int map_i[],
const int sections_i[],
const double gp[3],
const int k,
662 const int j,
const double exp_ij[],
const double exp_jk[],
663 const double exp_ik[],
const double dj,
double *ci,
667#if (GRID_DO_COLLOCATE)
671 map_i, sections_i, gp, k, j,
exp_ij, exp_jk, exp_ik, ci,
676 map_i, sections_i, gp, k, j,
exp_ij, exp_jk, exp_ik, ci,
687 const int lp,
const int k,
const int kg,
const int npts_local[3],
688 const int index_min[3],
const int index_max[3],
const int map_i[],
689 const int map_j[],
const int sections_i[],
const int sections_j[],
690 const double dh[3][3],
const double gp[3],
const double radius,
691 const double exp_ij[],
const double exp_jk[],
const double exp_ik[],
696 dh[0][0] * dh[0][0] + dh[0][1] * dh[0][1] + dh[0][2] * dh[0][2];
697 const double inv_2a = 1.0 / (2.0 *
a);
698 const double radius2 = radius * radius;
699 const double gp0_dh0[3] = {(0 - gp[0]) * dh[0][0], (0 - gp[0]) * dh[0][1],
700 (0 - gp[0]) * dh[0][2]};
701 const double dk_dh2[3] = {(k - gp[2]) * dh[2][0], (k - gp[2]) * dh[2][1],
702 (k - gp[2]) * dh[2][2]};
704 for (
int j = index_min[1]; j <= index_max[1]; j++) {
705 const int jg = map_j[j - index_min[1]];
707 j += sections_j[j - index_min[1]];
730 const double dj = j - gp[1];
731 double b = 0.0,
c = 0.0;
732 for (
int i = 0;
i < 3;
i++) {
733 const double v = (gp0_dh0[
i] + dj * dh[1][
i]) + dk_dh2[
i];
734 b += 2.0 * v * dh[0][
i];
737 const double d =
b *
b - 4.0 *
a * (
c - radius2);
740 const double sqrt_d = sqrt(d);
741 const int ismin = (int)ceil((-b - sqrt_d) * inv_2a);
742 const int ismax = (int)floor((-b + sqrt_d) * inv_2a);
745 memset(ci, 0,
sizeof(ci));
749 general_cij_to_grid_low(lp, jg, kg, ismin, ismax,
npts_local, index_min,
750 index_max, map_i, sections_i, gp, k, j,
exp_ij,
751 exp_jk, exp_ik, dj, ci, cij,
grid);
764 for (
int kl = 0; kl <= lp; kl++) {
765 for (
int jl = 0; jl <= lp - kl; jl++) {
766 for (
int il = 0; il <= lp - kl - jl; il++) {
767 const int cij_index = jl * (lp + 1) + il;
768 const int cijk_index =
769 kl * (lp + 1) * (lp + 1) + jl * (lp + 1) + il;
770#if (GRID_DO_COLLOCATE)
771 cij[cij_index] += cijk[cijk_index] * dkp;
773 cijk[cijk_index] += cij[cij_index] * dkp;
788 const int shift_local,
const int npts_global,
792 bool has_valid =
false;
793 for (
int k = index_min; k <= index_max; k++) {
794 const int kg =
modulo(k - shift_local, npts_global);
795 if (bounds[0] <= kg && kg <= bounds[1]) {
796 map[k - index_min] = kg;
799 map[k - index_min] = INT_MIN;
808 const int range = index_max - index_min + 1;
809 for (
int kg = range - 1; kg >= 0; kg--) {
810 if (kg == range - 1 ||
map[kg] !=
map[kg + 1] - 1) {
825 const int index_max[3],
const double zetp,
826 const double dh[3][3],
const double gp[3],
827 double exp_table[]) {
829 const int stride_i = index_max[idir] - index_min[idir] + 1;
830 const double h_ii = dh[idir][0] * dh[idir][0] + dh[idir][1] * dh[idir][1] +
831 dh[idir][2] * dh[idir][2];
832 const double h_jj = dh[jdir][0] * dh[jdir][0] + dh[jdir][1] * dh[jdir][1] +
833 dh[jdir][2] * dh[jdir][2];
834 const double h_ij = dh[idir][0] * dh[jdir][0] + dh[idir][1] * dh[jdir][1] +
835 dh[idir][2] * dh[jdir][2];
837 double exp_half_i[stride_i];
838 for (
int i = index_min[idir];
i <= index_max[idir];
i++) {
839 const double di =
i - gp[idir];
840 exp_half_i[
i - index_min[idir]] = exp(-0.5 * zetp * di * di * h_ii);
843 for (
int j = index_min[jdir]; j <= index_max[jdir]; j++) {
844 const double dj = j - gp[jdir];
845 const double rjj = 0.5 * dj * dj * h_jj;
846 const double rij_unit = dj * h_ij;
847 const double exp_ij_unit = exp(-zetp * 2.0 * rij_unit);
850 const int i_center = (int)gp[idir];
851 const double di_center = i_center - gp[idir];
852 const double rij_center = di_center * rij_unit;
853 const double exp_ij_center = exp(-zetp * (rjj + 2.0 * rij_center));
856 double exp_ij = exp_ij_center;
857 for (
int i = i_center;
i <= index_max[idir];
i++) {
858 const int idx = (j - index_min[jdir]) * stride_i +
i - index_min[idir];
859 exp_table[
idx] =
exp_ij * exp_half_i[
i - index_min[idir]];
864 const double exp_ij_unit_inv = 1.0 / exp_ij_unit;
865 exp_ij = exp_ij_center * exp_ij_unit_inv;
866 for (
int i = i_center - 1;
i >= index_min[idir];
i--) {
867 const int idx = (j - index_min[jdir]) * stride_i +
i - index_min[idir];
868 exp_table[
idx] =
exp_ij * exp_half_i[
i - index_min[idir]];
869 exp_ij *= exp_ij_unit_inv;
878static inline void __attribute__((always_inline)) general_cijk_kloop_low(
879 const int lp,
const int npts_local[3],
const int index_min[3],
880 const int index_max[3],
const int map_i[],
const int map_j[],
881 const int map_k[],
const int sections_i[],
const int sections_j[],
882 const int sections_k[],
const double dh[3][3],
const double gp[3],
883 const double radius,
const double exp_ij[],
const double exp_jk[],
887 const int cij_size = (lp + 1) * (lp + 1);
888 for (
int k = index_min[2]; k <= index_max[2]; k++) {
889 const int kg = map_k[k - index_min[2]];
891 k += sections_k[k - index_min[2]];
896 memset(cij, 0, cij_size *
sizeof(
double));
898#if (GRID_DO_COLLOCATE)
902 map_j, sections_i, sections_j, dh, gp, radius,
exp_ij,
903 exp_jk, exp_ik, cij,
grid);
907 map_j, sections_i, sections_j, dh, gp, radius,
exp_ij,
908 exp_jk, exp_ik, cij,
grid);
923 const double dh[3][3],
const double dh_inv[3][3],
924 const double rp[3],
const int npts_global[3],
925 const int npts_local[3],
const int shift_local[3],
926 const int border_width[3],
const double radius,
937 if (border_mask & (1 << 0))
938 bounds_i[0] += border_width[0];
939 if (border_mask & (1 << 1))
940 bounds_i[1] -= border_width[0];
941 if (border_mask & (1 << 2))
942 bounds_j[0] += border_width[1];
943 if (border_mask & (1 << 3))
944 bounds_j[1] -= border_width[1];
945 if (border_mask & (1 << 4))
946 bounds_k[0] += border_width[2];
947 if (border_mask & (1 << 5))
948 bounds_k[1] -= border_width[2];
950 if (bounds_i[0] > bounds_i[1] || bounds_j[0] > bounds_j[1] ||
951 bounds_k[0] > bounds_k[1]) {
957 double gp[3] = {0.0, 0.0, 0.0};
958 for (
int i = 0;
i < 3;
i++) {
959 for (
int j = 0; j < 3; j++) {
960 gp[
i] += dh_inv[j][
i] * rp[j];
970 const double sphere_bound_eps = 1.0 + 1e-12;
973 for (
int idir = 0; idir < 3; idir++) {
974 const double norm = sqrt(dh_inv[0][idir] * dh_inv[0][idir] +
975 dh_inv[1][idir] * dh_inv[1][idir] +
976 dh_inv[2][idir] * dh_inv[2][idir]);
977 const double rad_idx = radius * norm * sphere_bound_eps;
978 index_min[idir] = (int)floor(gp[idir] - rad_idx);
979 index_max[idir] = (int)ceil(gp[idir] + rad_idx);
984 const int range_i = index_max[0] - index_min[0] + 1;
985 const int range_j = index_max[1] - index_min[1] + 1;
986 const int range_k = index_max[2] - index_min[2] + 1;
987 const size_t exp_count = (size_t)range_i * range_j +
988 (
size_t)range_j * range_k +
989 (size_t)range_k * range_i;
990 const size_t map_count = 2 * ((size_t)range_i + range_j + range_k);
992 exp_count *
sizeof(
double) + map_count *
sizeof(
int));
993 double *restrict
const exp_ij = scratch;
994 double *restrict
const exp_jk =
exp_ij + (size_t)range_i * range_j;
995 double *restrict
const exp_ik = exp_jk + (size_t)range_j * range_k;
996 int *restrict
const map_i = (
int *)(exp_ik + (
size_t)range_k * range_i);
997 int *restrict
const sections_i = map_i + range_i;
998 int *restrict
const map_j = sections_i + range_i;
999 int *restrict
const sections_j = map_j + range_j;
1000 int *restrict
const map_k = sections_j + range_j;
1001 int *restrict
const sections_k = map_k + range_k;
1003 npts_global[0], bounds_i, map_i,
1008 npts_global[1], bounds_j, map_j,
1013 npts_global[2], bounds_k, map_k,
1024 const int cij_size = (lp + 1) * (lp + 1);
1025 double cij[cij_size];
1031 general_cijk_kloop_low(ilp,
npts_local, index_min, index_max, map_i,
1032 map_j, map_k, sections_i, sections_j, sections_k,
1033 dh, gp, radius,
exp_ij, exp_jk, exp_ik, cij,
1038 general_cijk_kloop_low(lp,
npts_local, index_min, index_max, map_i, map_j,
1039 map_k, sections_i, sections_j, sections_k, dh, gp,
1040 radius,
exp_ij, exp_jk, exp_ik, cij, cijk,
grid);
1058 const int lp1 = lp + 1;
1059 double hmatgridp[lp1][3][3];
1060 for (
int i = 0;
i < 3;
i++) {
1061 for (
int j = 0; j < 3; j++) {
1062 hmatgridp[0][j][
i] = 1.0;
1063 for (
int k = 1; k <= lp; k++) {
1064 hmatgridp[k][j][
i] = hmatgridp[k - 1][j][
i] * dh[j][
i];
1069 double trinom[3][lp1][lp1][lp1];
1070 for (
int d = 0;
d < 3;
d++) {
1071 for (
int kl = 0; kl <= lp; kl++) {
1072 for (
int jl = 0; jl <= lp - kl; jl++) {
1073 for (
int il = 0; il <= lp - kl - jl; il++) {
1074 const int l = il + jl + kl;
1075 trinom[
d][kl][jl][il] = hmatgridp[il][0][
d] * hmatgridp[jl][1][
d] *
1076 hmatgridp[kl][2][
d] *
fac(l) /
1084 for (
int klx = 0; klx <= lpx; klx++) {
1085 for (
int jlx = 0; jlx <= lpx - klx; jlx++) {
1086 for (
int ilx = 0; ilx <= lpx - klx - jlx; ilx++) {
1087 const int lx = ilx + jlx + klx;
1088 const double px = trinom[0][klx][jlx][ilx];
1089 const int lpy = lp - lx;
1090 for (
int kly = 0; kly <= lpy; kly++) {
1091 for (
int jly = 0; jly <= lpy - kly; jly++) {
1092 for (
int ily = 0; ily <= lpy - kly - jly; ily++) {
1093 const int ly = ily + jly + kly;
1094 const double pxy = px * trinom[1][kly][jly][ily];
1095 const int il_xy = ilx + ily;
1096 const int jl_xy = jlx + jly;
1097 const int kl_xy = klx + kly;
1098 const int lpz = lp - lx - ly;
1099 const int cxyz_base = ly * lp1 + lx;
1100 for (
int klz = 0; klz <= lpz; klz++) {
1101 const int kl_base = (kl_xy + klz) * lp1 * lp1;
1102 for (
int jlz = 0; jlz <= lpz - klz; jlz++) {
1103 const int cijk_base = kl_base + (jl_xy + jlz) * lp1 + il_xy;
1104 for (
int ilz = 0; ilz <= lpz - klz - jlz; ilz++) {
1105 const int lz = ilz + jlz + klz;
1106 const int cijk_index = cijk_base + ilz;
1107 const int cxyz_index =
1108 lz * lp1 * lp1 + cxyz_base;
1109 const double p = pxy * trinom[2][klz][jlz][ilz];
1110#if (GRID_DO_COLLOCATE)
1111 cijk[cijk_index] += cxyz[cxyz_index] *
p;
1113 cxyz[cxyz_index] += cijk[cijk_index] *
p;
1132 const double dh[3][3],
const double dh_inv[3][3],
1133 const double rp[3],
const int npts_global[3],
1134 const int npts_local[3],
const int shift_local[3],
1135 const int border_width[3],
const double radius,
1139 const size_t cijk_size = (lp + 1) * (lp + 1) * (lp + 1);
1140 double cijk[cijk_size];
1141 memset(cijk, 0, cijk_size *
sizeof(
double));
1143#if (GRID_DO_COLLOCATE)
1147 npts_local, shift_local, border_width, radius, cijk,
1152 npts_local, shift_local, border_width, radius, cijk,
1163cxyz_to_grid(
const bool orthorhombic,
const int border_mask,
const int lp,
1164 const double zetp,
const double dh[3][3],
1165 const double dh_inv[3][3],
const double rp[3],
1166 const int npts_global[3],
const int npts_local[3],
1167 const int shift_local[3],
const int border_width[3],
1172 if (orthorhombic && border_mask == 0) {
1175 shift_local, radius, cxyz,
grid);
1179 npts_local, shift_local, border_width, radius, cxyz,
1189static inline void cab_to_cxyz(
const int la_max,
const int la_min,
1190 const int lb_max,
const int lb_min,
1191 const double prefactor,
const double ra[3],
1192 const double rb[3],
const double rp[3],
1198 const int lp = la_max + lb_max;
1199 const int lp1 = lp + 1;
1200 double alpha[3][lb_max + 1][la_max + 1][lp + 1];
1202 for (
int i = 0;
i < 3;
i++) {
1203 const double drpa = rp[
i] - ra[
i];
1204 const double drpb = rp[
i] - rb[
i];
1205 alpha[
i][0][0][0] = 1.0;
1206 for (
int lxa = 1; lxa <= la_max; lxa++) {
1207 alpha[
i][0][lxa][0] = drpa * alpha[
i][0][lxa - 1][0];
1208 for (
int k = 1; k < lxa; k++) {
1209 alpha[
i][0][lxa][k] =
1210 alpha[
i][0][lxa - 1][k - 1] + drpa * alpha[
i][0][lxa - 1][k];
1212 alpha[
i][0][lxa][lxa] = 1.0;
1214 for (
int lxb = 1; lxb <= lb_max; lxb++) {
1215 for (
int lxa = 0; lxa <= la_max; lxa++) {
1216 const int n = lxa + lxb;
1217 alpha[
i][lxb][lxa][0] = drpb * alpha[
i][lxb - 1][lxa][0];
1218 for (
int k = 1; k < n; k++) {
1219 alpha[
i][lxb][lxa][k] =
1220 alpha[
i][lxb - 1][lxa][k - 1] + drpb * alpha[
i][lxb - 1][lxa][k];
1222 alpha[
i][lxb][lxa][n] = 1.0;
1242 const int ncoset_a =
ncoset(la_max);
1243 double txy[lp1 * lp1];
1246#if (GRID_DO_COLLOCATE)
1247 for (
int lzb = 0; lzb <= lb_max; lzb++) {
1248 for (
int lza = 0; lza <= la_max; lza++) {
1249 const int lz_max = lza + lzb;
1250 const int lyp_max = lp - lz_max;
1251 memset(txy, 0, (lyp_max + 1) * lp1 *
sizeof(
double));
1252 for (
int lyb = 0; lyb <= lb_max - lzb; lyb++) {
1253 for (
int lya = 0; lya <= la_max - lza; lya++) {
1254 const int ly_max = lya + lyb;
1255 const int lxb_min =
imax(lb_min - lzb - lyb, 0);
1256 const int lxa_min =
imax(la_min - lza - lya, 0);
1257 const int lxb_max = lb_max - lzb - lyb;
1258 const int lxa_max = la_max - lza - lya;
1259 const int lxp_max = lxa_max + lxb_max;
1260 memset(tx, 0, (lxp_max + 1) *
sizeof(
double));
1261 for (
int lxb = lxb_min; lxb <= lxb_max; lxb++) {
1262 const int jco =
coset(lxb, lyb, lzb);
1263 for (
int lxa = lxa_min; lxa <= lxa_max; lxa++) {
1264 const int ico =
coset(lxa, lya, lza);
1265 const int cab_index = jco * ncoset_a + ico;
1266 const double cab_val = cab[cab_index] * prefactor;
1267 for (
int lxp = 0; lxp <= lxa + lxb; lxp++) {
1268 tx[lxp] += cab_val * alpha[0][lxb][lxa][lxp];
1272 for (
int lyp = 0; lyp <= ly_max; lyp++) {
1273 const double ay = alpha[1][lyb][lya][lyp];
1274 double *txy_row = &txy[lyp * lp1];
1275 for (
int lxp = 0; lxp <= lxp_max; lxp++) {
1276 txy_row[lxp] += tx[lxp] * ay;
1281 for (
int lzp = 0; lzp <= lz_max; lzp++) {
1282 const double az = alpha[2][lzb][lza][lzp];
1283 double *cxyz_z = &cxyz[lzp * lp1 * lp1];
1284 for (
int lyp = 0; lyp <= lyp_max; lyp++) {
1285 const double *txy_row = &txy[lyp * lp1];
1286 double *cxyz_zy = &cxyz_z[lyp * lp1];
1287 for (
int lxp = 0; lxp <= lyp_max - lyp; lxp++) {
1288 cxyz_zy[lxp] += txy_row[lxp] * az;
1295 for (
int lzb = 0; lzb <= lb_max; lzb++) {
1296 for (
int lza = 0; lza <= la_max; lza++) {
1297 const int lz_max = lza + lzb;
1298 const int lyp_max = lp - lz_max;
1299 memset(txy, 0, (lyp_max + 1) * lp1 *
sizeof(
double));
1300 for (
int lzp = 0; lzp <= lz_max; lzp++) {
1301 const double az = alpha[2][lzb][lza][lzp] * prefactor;
1302 const double *cxyz_z = &cxyz[lzp * lp1 * lp1];
1303 for (
int lyp = 0; lyp <= lyp_max; lyp++) {
1304 double *txy_row = &txy[lyp * lp1];
1305 const double *cxyz_zy = &cxyz_z[lyp * lp1];
1306 for (
int lxp = 0; lxp <= lyp_max - lyp; lxp++) {
1307 txy_row[lxp] += cxyz_zy[lxp] * az;
1311 for (
int lyb = 0; lyb <= lb_max - lzb; lyb++) {
1312 for (
int lya = 0; lya <= la_max - lza; lya++) {
1313 const int ly_max = lya + lyb;
1314 const int lxb_min =
imax(lb_min - lzb - lyb, 0);
1315 const int lxa_min =
imax(la_min - lza - lya, 0);
1316 const int lxb_max = lb_max - lzb - lyb;
1317 const int lxa_max = la_max - lza - lya;
1318 const int lxp_max = lxa_max + lxb_max;
1319 memset(tx, 0, (lxp_max + 1) *
sizeof(
double));
1320 for (
int lyp = 0; lyp <= ly_max; lyp++) {
1321 const double ay = alpha[1][lyb][lya][lyp];
1322 const double *txy_row = &txy[lyp * lp1];
1323 for (
int lxp = 0; lxp <= lxp_max; lxp++) {
1324 tx[lxp] += txy_row[lxp] * ay;
1327 for (
int lxb = lxb_min; lxb <= lxb_max; lxb++) {
1328 const int jco =
coset(lxb, lyb, lzb);
1329 for (
int lxa = lxa_min; lxa <= lxa_max; lxa++) {
1330 const int ico =
coset(lxa, lya, lza);
1331 const int cab_index = jco * ncoset_a + ico;
1333 for (
int lxp = 0; lxp <= lxa + lxb; lxp++) {
1334 sum_x += tx[lxp] * alpha[0][lxb][lxa][lxp];
1336 cab[cab_index] += sum_x;
1351cab_to_grid(
const bool orthorhombic,
const int border_mask,
const int la_max,
1352 const int la_min,
const int lb_max,
const int lb_min,
1353 const double zeta,
const double zetb,
const double rscale,
1354 const double dh[3][3],
const double dh_inv[3][3],
1355 const double ra[3],
const double rab[3],
const int npts_global[3],
1356 const int npts_local[3],
const int shift_local[3],
1357 const int border_width[3],
const double radius,
1362 double dh_max = 0.0;
1363 for (
int i = 0;
i < 3;
i++) {
1364 for (
int j = 0; j < 3; j++) {
1365 dh_max = fmax(dh_max, fabs(dh[
i][j]));
1368 if (2.0 * radius < dh_max) {
1372 const double zetp =
zeta + zetb;
1373 const double f = zetb / zetp;
1374 const double rab2 = rab[0] * rab[0] + rab[1] * rab[1] + rab[2] * rab[2];
1375 const double prefactor = rscale * exp(-zeta * f * rab2);
1376 double rp[3], rb[3];
1377 for (
int i = 0;
i < 3;
i++) {
1378 rp[
i] = ra[
i] + f * rab[
i];
1379 rb[
i] = ra[
i] + rab[
i];
1382 const int lp = la_max + lb_max;
1383 const size_t cxyz_size = (lp + 1) * (lp + 1) * (lp + 1);
1384 double cxyz[cxyz_size];
1385 memset(cxyz, 0, cxyz_size *
sizeof(
double));
1387#if (GRID_DO_COLLOCATE)
1389 cab_to_cxyz(la_max, la_min, lb_max, lb_min, prefactor, ra, rb, rp, cab, cxyz);
1390 cxyz_to_grid(orthorhombic, border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
1394 cxyz_to_grid(orthorhombic, border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
1396 cab_to_cxyz(la_max, la_min, lb_max, lb_min, prefactor, ra, rb, rp, cab, cxyz);
static int imax(int x, int y)
Returns the larger of two given integers (missing from the C standard).
static int imin(int x, int y)
Returns the smaller of the two integers (missing from the C standard).
static GRID_HOST_DEVICE int coset(int lx, int ly, int lz)
Maps three angular momentum components to a single zero based index.
static GRID_HOST_DEVICE int ncoset(const int l)
Number of Cartesian orbitals up to given angular momentum quantum.
#define GRID_PRAGMA_UNROLL_UP_TO(N)
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
static GRID_HOST_DEVICE double fac(const int i)
Factorial function, e.g. fac(5) = 5! = 120.
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
#define GRID_PRAGMA_UNROLL(N)
static void const int const int const int const int const int const double const int const int const int int GRID_CONST_WHEN_COLLOCATE double GRID_CONST_WHEN_INTEGRATE double * grid
#define GRID_CONST_WHEN_COLLOCATE
static void const int const int const double GRID_CONST_WHEN_COLLOCATE double GRID_CONST_WHEN_INTEGRATE double GRID_CONST_WHEN_INTEGRATE double GRID_CONST_WHEN_INTEGRATE double * grid_2
static void const int const int const int jg1
static void const int const int j2
static void const int const int const double GRID_CONST_WHEN_COLLOCATE double GRID_CONST_WHEN_INTEGRATE double GRID_CONST_WHEN_INTEGRATE double * grid_1
static void const int const int const int const int const int const double const int const int const int int ** sphere_bounds_iter
static void const int const int kg2
static void const int const int const int const int const int const double const int const int sections[3][2 *cmax+1]
static void const int const int i
static void const int const int const int const double GRID_CONST_WHEN_COLLOCATE double * cxy
static void __attribute__((always_inline)) ortho_cx_to_grid_scalar(const int lp
Simple loop body for ortho_cx_to_grid using plain C.
static void const int cmax
static void const int kg1
static void const int const int const double pol[3][lp+1][2 *cmax+1]
static void const int const int const int const int const int const double const int const int const int npts_local[3]
#define GRID_MAX_LP_OPTIMIZED
static void const int const int const int const int jg2
static void const int const int const double GRID_CONST_WHEN_COLLOCATE double GRID_CONST_WHEN_INTEGRATE double * grid_0
for(int lxp=0;lxp<=lp;lxp++)
static void const int const int const double GRID_CONST_WHEN_COLLOCATE double GRID_CONST_WHEN_INTEGRATE double GRID_CONST_WHEN_INTEGRATE double GRID_CONST_WHEN_INTEGRATE double GRID_CONST_WHEN_INTEGRATE double * grid_3
static void const int const int const int const int const int const double const int map[3][2 *cmax+1]
#define GRID_CONST_WHEN_INTEGRATE
static void const int const int const double GRID_CONST_WHEN_COLLOCATE double * cx
#define GRID_DO_COLLOCATE
void exp_ij(const double alpha, const int offset_i, const int imin, const int imax, const int offset_j, const int jmin, const int jmax, tensor *exp_ij_)
void * grid_library_get_scratch(const size_t bytes)
Returns a pointer to a thread local scratch buffer with at least the given size. The buffer grows on ...
void grid_library_counter_add(const int lp, const enum grid_backend backend, const enum grid_library_kernel kernel, const int increment)
Adds given increment to counter specified by lp, backend, and kernel.
grid_library_kernel
Various kernels provided by the grid library.
static void cxyz_to_grid(const bool orthorhombic, const int border_mask, const int lp, const double zetp, const double dh[3][3], const double dh_inv[3][3], const double rp[3], const int npts_global[3], const int npts_local[3], const int shift_local[3], const int border_width[3], const double radius, GRID_CONST_WHEN_COLLOCATE double *cxyz, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_xyz onto the grid.
static void cab_to_cxyz(const int la_max, const int la_min, const int lb_max, const int lb_min, const double prefactor, const double ra[3], const double rb[3], const double rp[3], GRID_CONST_WHEN_COLLOCATE double *cab, GRID_CONST_WHEN_INTEGRATE double *cxyz)
Transforms coefficients C_ab into C_xyz.
static void ortho_cxy_to_grid(const int lp, const int k1, const int k2, const int cmax, const double pol[3][lp+1][2 *cmax+1], const int map[3][2 *cmax+1], const double dh[3][3], const double dh_inv[3][3], const double disr_radius, const int npts_local[3], GRID_CONST_WHEN_COLLOCATE double *cxy, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_xy onto the grid for orthorhombic case.
static void general_cij_to_ci(const int lp, const double dj, GRID_CONST_WHEN_COLLOCATE double *cij, GRID_CONST_WHEN_INTEGRATE double *ci)
Transforms coefficients C_ij into C_i by fixing grid index j.
static void general_cijk_to_cij(const int lp, const double dk, GRID_CONST_WHEN_COLLOCATE double *cijk, GRID_CONST_WHEN_INTEGRATE double *cij)
Transforms coefficients C_ijk into C_ij by fixing grid index k.
static void general_precompute_mapping(const int index_min, const int index_max, const int shift_local, const int npts_global, const int bounds[2], int map[])
Precompute mapping of grid indices for general case.
static void ortho_cxy_to_cx(const int lp, const int j1, const int j2, const int cmax, const double pol[3][lp+1][2 *cmax+1], GRID_CONST_WHEN_COLLOCATE double *cxy, GRID_CONST_WHEN_INTEGRATE double *cx)
Transforms coefficients C_xy into C_x by fixing grid index j.
static void general_cxyz_to_cijk(const int lp, const double dh[3][3], GRID_CONST_WHEN_COLLOCATE double *cxyz, GRID_CONST_WHEN_INTEGRATE double *cijk)
Transforms coefficients C_xyz into C_ijk.
static void general_cij_to_grid(const int lp, const int k, const int kg, const int npts_local[3], const int index_min[3], const int index_max[3], const int map_i[], const int map_j[], const double dh[3][3], const double gp[3], const double radius, const double exp_ij[], const double exp_jk[], const double exp_ki[], GRID_CONST_WHEN_COLLOCATE double *cij, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_ij onto the grid for general case.
static void general_cijk_to_grid(const int border_mask, const int lp, const double zetp, const double dh[3][3], const double dh_inv[3][3], const double rp[3], const int npts_global[3], const int npts_local[3], const int shift_local[3], const int border_width[3], const double radius, GRID_CONST_WHEN_COLLOCATE double *cijk, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_ijk onto the grid for general case.
static void cab_to_grid(const bool orthorhombic, const int border_mask, const int la_max, const int la_min, const int lb_max, const int lb_min, const double zeta, const double zetb, const double rscale, const double dh[3][3], const double dh_inv[3][3], const double ra[3], const double rab[3], const int npts_global[3], const int npts_local[3], const int shift_local[3], const int border_width[3], const double radius, GRID_CONST_WHEN_COLLOCATE double *cab, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_ab onto the grid.
static void general_ci_to_grid(const int lp, const int jg, const int kg, const int ismin, const int ismax, const int npts_local[3], const int index_min[3], const int index_max[3], const int map_i[], const double gp[3], const int k, const int j, const double exp_ij[], const double exp_jk[], const double exp_ki[], GRID_CONST_WHEN_COLLOCATE double *ci, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_i onto the grid for general case.
static void ortho_cx_to_grid(const int lp, const int k1, const int k2, const int j1, const int j2, const int cmax, const double pol[3][lp+1][2 *cmax+1], const int map[3][2 *cmax+1], const double dh[3][3], const double dh_inv[3][3], const double kremain, const int npts_local[3], GRID_CONST_WHEN_COLLOCATE double *cx, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_x onto the grid for orthorhombic case.
static void ortho_cxyz_to_cxy(const int lp, const int k1, const int k2, const int cmax, const double pol[3][lp+1][2 *cmax+1], GRID_CONST_WHEN_COLLOCATE double *cxyz, GRID_CONST_WHEN_INTEGRATE double *cxy)
Transforms coefficients C_xyz into C_xz by fixing grid index k.
static void general_cxyz_to_grid(const int border_mask, const int lp, const double zetp, const double dh[3][3], const double dh_inv[3][3], const double rp[3], const int npts_global[3], const int npts_local[3], const int shift_local[3], const int border_width[3], const double radius, GRID_CONST_WHEN_COLLOCATE double *cxyz, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_xyz onto the grid for general case.
static void ortho_cxyz_to_grid(const int lp, const double zetp, const double dh[3][3], const double dh_inv[3][3], const double rp[3], const int npts_global[3], const int npts_local[3], const int shift_local[3], const double radius, GRID_CONST_WHEN_COLLOCATE double *cxyz, GRID_CONST_WHEN_INTEGRATE double *grid)
Collocates coefficients C_xyz onto the grid for orthorhombic case.
static void general_fill_exp_table(const int idir, const int jdir, const int index_min[3], const int index_max[3], const double zetp, const double dh[3][3], const double gp[3], double exp_table[])
Fill one of the 2D tables that speedup 3D Gaussian (Mathieu's trick).
void grid_sphere_cache_lookup(const double radius, const double dh[3][3], const double dh_inv[3][3], int **sphere_bounds, double *discr_radius)
Lookup the sphere bound from cache and compute them as needed. See grid_sphere_cache....
integer, parameter, public gaussian