(git:e7e05ae)
grid_ref_collint.h
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* CP2K: A general program to perform molecular dynamics simulations */
3 /* Copyright 2000-2024 CP2K developers group <https://cp2k.org> */
4 /* */
5 /* SPDX-License-Identifier: BSD-3-Clause */
6 /*----------------------------------------------------------------------------*/
7 
8 #include <assert.h>
9 #include <limits.h>
10 #include <math.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "../common/grid_common.h"
16 #include "../common/grid_library.h"
17 
18 #if (GRID_DO_COLLOCATE)
19 #define GRID_CONST_WHEN_COLLOCATE const
20 #define GRID_CONST_WHEN_INTEGRATE
21 #else
22 #define GRID_CONST_WHEN_COLLOCATE
23 #define GRID_CONST_WHEN_INTEGRATE const
24 #endif
25 
26 /*******************************************************************************
27  * \brief Collocates coefficients C_x onto the grid for orthorhombic case.
28  * \author Ole Schuett
29  ******************************************************************************/
30 static inline void
31 ortho_cx_to_grid(const int lp, const int k1, const int k2, const int j1,
32  const int j2, const int cmax,
33  const double pol[3][lp + 1][2 * cmax + 1],
34  const int map[3][2 * cmax + 1], const double dh[3][3],
35  const double dh_inv[3][3], const double kremain,
36  const int npts_local[3], GRID_CONST_WHEN_COLLOCATE double *cx,
38 
39  const int kg1 = map[2][k1 + cmax];
40  const int kg2 = map[2][k2 + cmax];
41  const int jg1 = map[1][j1 + cmax];
42  const int jg2 = map[1][j2 + cmax];
43 
44  // For this innermost dimension we're going sequentially instead of in pairs.
45  // Hence we're processing four points at once, which is well suited for AVX2.
46  const int jd = (2 * j1 - 1) / 2; // distance from center in grid points
47  const double jr = jd * dh[1][1]; // distance from center in a.u.
48  const double jremain = kremain - jr * jr;
49  const int istart = (int)ceil(-1e-8 - sqrt(fmax(0.0, jremain)) * dh_inv[0][0]);
50  const int iend = 1 - istart;
51 
52  for (int i = istart; i <= iend; i++) {
53  const int ig = map[0][i + cmax];
54 
55  const int stride = npts_local[1] * npts_local[0];
56  const int grid_index_0 = kg1 * stride + jg1 * npts_local[0] + ig;
57  const int grid_index_1 = kg2 * stride + jg1 * npts_local[0] + ig;
58  const int grid_index_2 = kg1 * stride + jg2 * npts_local[0] + ig;
59  const int grid_index_3 = kg2 * stride + jg2 * npts_local[0] + ig;
60 
61  GRID_CONST_WHEN_INTEGRATE double *grid_0 = &grid[grid_index_0];
62  GRID_CONST_WHEN_INTEGRATE double *grid_1 = &grid[grid_index_1];
63  GRID_CONST_WHEN_INTEGRATE double *grid_2 = &grid[grid_index_2];
64  GRID_CONST_WHEN_INTEGRATE double *grid_3 = &grid[grid_index_3];
65 
66 #if (GRID_DO_COLLOCATE)
67  // collocate
68  double reg[4] = {0.0, 0.0, 0.0, 0.0};
69  for (int lxp = 0; lxp <= lp; lxp++) {
70  const double p = pol[0][lxp][i + cmax];
71  reg[0] += cx[lxp * 4 + 0] * p;
72  reg[1] += cx[lxp * 4 + 1] * p;
73  reg[2] += cx[lxp * 4 + 2] * p;
74  reg[3] += cx[lxp * 4 + 3] * p;
75  }
76  *grid_0 += reg[0];
77  *grid_1 += reg[1];
78  *grid_2 += reg[2];
79  *grid_3 += reg[3];
80 
81 #else
82  // integrate
83  const double reg[4] = {*grid_0, *grid_1, *grid_2, *grid_3};
84  for (int lxp = 0; lxp <= lp; lxp++) {
85  const double p = pol[0][lxp][i + cmax];
86  cx[lxp * 4 + 0] += reg[0] * p;
87  cx[lxp * 4 + 1] += reg[1] * p;
88  cx[lxp * 4 + 2] += reg[2] * p;
89  cx[lxp * 4 + 3] += reg[3] * p;
90  }
91 #endif
92  }
93 }
94 
95 /*******************************************************************************
96  * \brief Transforms coefficients C_xy into C_x by fixing grid index j.
97  * \author Ole Schuett
98  ******************************************************************************/
99 static inline void ortho_cxy_to_cx(const int lp, const int j1, const int j2,
100  const int cmax,
101  const double pol[3][lp + 1][2 * cmax + 1],
103  GRID_CONST_WHEN_INTEGRATE double *cx) {
104 
105  for (int lyp = 0; lyp <= lp; lyp++) {
106  for (int lxp = 0; lxp <= lp - lyp; lxp++) {
107  const double p1 = pol[1][lyp][j1 + cmax];
108  const double p2 = pol[1][lyp][j2 + cmax];
109  const int cxy_index = lyp * (lp + 1) * 2 + lxp * 2; // [lyp, lxp, 0]
110 
111 #if (GRID_DO_COLLOCATE)
112  // collocate
113  cx[lxp * 4 + 0] += cxy[cxy_index + 0] * p1;
114  cx[lxp * 4 + 1] += cxy[cxy_index + 1] * p1;
115  cx[lxp * 4 + 2] += cxy[cxy_index + 0] * p2;
116  cx[lxp * 4 + 3] += cxy[cxy_index + 1] * p2;
117 #else
118  // integrate
119  cxy[cxy_index + 0] += cx[lxp * 4 + 0] * p1;
120  cxy[cxy_index + 1] += cx[lxp * 4 + 1] * p1;
121  cxy[cxy_index + 0] += cx[lxp * 4 + 2] * p2;
122  cxy[cxy_index + 1] += cx[lxp * 4 + 3] * p2;
123 #endif
124  }
125  }
126 }
127 
128 /*******************************************************************************
129  * \brief Collocates coefficients C_xy onto the grid for orthorhombic case.
130  * \author Ole Schuett
131  ******************************************************************************/
132 static inline void ortho_cxy_to_grid(
133  const int lp, const int k1, const int k2, const int cmax,
134  const double pol[3][lp + 1][2 * cmax + 1], const int map[3][2 * cmax + 1],
135  const double dh[3][3], const double dh_inv[3][3], const double disr_radius,
136  const int npts_local[3], GRID_CONST_WHEN_COLLOCATE double *cxy,
138 
139  // The cube contains an even number of grid points in each direction and
140  // collocation is always performed on a pair of two opposing grid points.
141  // Hence, the points with index 0 and 1 are both assigned distance zero via
142  // the formular distance=(2*index-1)/2.
143 
144  const int kd = (2 * k1 - 1) / 2; // distance from center in grid points
145  const double kr = kd * dh[2][2]; // distance from center in a.u.
146  const double kremain = disr_radius * disr_radius - kr * kr;
147  const int jstart = (int)ceil(-1e-8 - sqrt(fmax(0.0, kremain)) * dh_inv[1][1]);
148 
149  const size_t cx_size = (lp + 1) * 4;
150  double cx[cx_size];
151  for (int j1 = jstart; j1 <= 0; j1++) {
152  const int j2 = 1 - j1;
153  memset(cx, 0, cx_size * sizeof(double));
154 
155 #if (GRID_DO_COLLOCATE)
156  // collocate
157  ortho_cxy_to_cx(lp, j1, j2, cmax, pol, cxy, cx);
158  ortho_cx_to_grid(lp, k1, k2, j1, j2, cmax, pol, map, dh, dh_inv, kremain,
159  npts_local, cx, grid);
160 #else
161  // integrate
162  ortho_cx_to_grid(lp, k1, k2, j1, j2, cmax, pol, map, dh, dh_inv, kremain,
163  npts_local, cx, grid);
164  ortho_cxy_to_cx(lp, j1, j2, cmax, pol, cxy, cx);
165 #endif
166  }
167 }
168 
169 /*******************************************************************************
170  * \brief Transforms coefficients C_xyz into C_xz by fixing grid index k.
171  * \author Ole Schuett
172  ******************************************************************************/
173 static inline void ortho_cxyz_to_cxy(const int lp, const int k1, const int k2,
174  const int cmax,
175  const double pol[3][lp + 1][2 * cmax + 1],
176  GRID_CONST_WHEN_COLLOCATE double *cxyz,
177  GRID_CONST_WHEN_INTEGRATE double *cxy) {
178 
179  for (int lzp = 0; lzp <= lp; lzp++) {
180  for (int lyp = 0; lyp <= lp - lzp; lyp++) {
181  for (int lxp = 0; lxp <= lp - lzp - lyp; lxp++) {
182  const double p1 = pol[2][lzp][k1 + cmax];
183  const double p2 = pol[2][lzp][k2 + cmax];
184  const int cxyz_index =
185  lzp * (lp + 1) * (lp + 1) + lyp * (lp + 1) + lxp; // [lzp, lyp, lxp]
186  const int cxy_index = lyp * (lp + 1) * 2 + lxp * 2; // [lyp, lxp, 0]
187 
188 #if (GRID_DO_COLLOCATE)
189  // collocate
190  cxy[cxy_index + 0] += cxyz[cxyz_index] * p1;
191  cxy[cxy_index + 1] += cxyz[cxyz_index] * p2;
192 #else
193  // integrate
194  cxyz[cxyz_index] += cxy[cxy_index + 0] * p1;
195  cxyz[cxyz_index] += cxy[cxy_index + 1] * p2;
196 #endif
197  }
198  }
199  }
200 }
201 
202 /*******************************************************************************
203  * \brief Collocates coefficients C_xyz onto the grid for orthorhombic case.
204  * \author Ole Schuett
205  ******************************************************************************/
206 static inline void
207 ortho_cxyz_to_grid(const int lp, const double zetp, const double dh[3][3],
208  const double dh_inv[3][3], const double rp[3],
209  const int npts_global[3], const int npts_local[3],
210  const int shift_local[3], const double radius,
211  GRID_CONST_WHEN_COLLOCATE double *cxyz,
213 
214  // *** position of the gaussian product
215  //
216  // this is the actual definition of the position on the grid
217  // i.e. a point rp(:) gets here grid coordinates
218  // MODULO(rp(:)/dr(:),npts_global(:))+1
219  // hence (0.0,0.0,0.0) in real space is rsgrid%lb on the rsgrid in Fortran
220  // and (1,1,1) on grid here in C.
221 
222  // cubecenter(:) = FLOOR(MATMUL(dh_inv, rp))
223  int cubecenter[3];
224  for (int i = 0; i < 3; i++) {
225  double dh_inv_rp = 0.0;
226  for (int j = 0; j < 3; j++) {
227  dh_inv_rp += dh_inv[j][i] * rp[j];
228  }
229  cubecenter[i] = (int)floor(dh_inv_rp);
230  }
231 
232  double roffset[3];
233  for (int i = 0; i < 3; i++) {
234  roffset[i] = rp[i] - ((double)cubecenter[i]) * dh[i][i];
235  }
236 
237  // Historically, the radius gets discretized to make sphere bounds cacheable.
238  const double drmin = fmin(dh[0][0], fmin(dh[1][1], dh[2][2]));
239  const double disr_radius = drmin * fmax(1.0, ceil(radius / drmin));
240 
241  // Cube bounds.
242  int lb_cube[3], ub_cube[3];
243  for (int i = 0; i < 3; i++) {
244  lb_cube[i] = (int)ceil(-1e-8 - disr_radius * dh_inv[i][i]);
245  ub_cube[i] = 1 - lb_cube[i];
246  // If grid is not period check that cube fits without wrapping.
247  if (npts_global[i] != npts_local[i]) {
248  const int offset =
249  modulo(cubecenter[i] + lb_cube[i] - shift_local[i], npts_global[i]) -
250  lb_cube[i];
251  assert(offset + ub_cube[i] < npts_local[i]);
252  assert(offset + lb_cube[i] >= 0);
253  }
254  }
255 
256  // cmax = MAXVAL(ub_cube)
257  const int cmax = imax(imax(ub_cube[0], ub_cube[1]), ub_cube[2]);
258 
259  // Precompute (x-xp)**lp*exp(..) for each direction.
260  double pol_mutable[3][lp + 1][2 * cmax + 1];
261  for (int idir = 0; idir < 3; idir++) {
262  const double dr = dh[idir][idir];
263  const double ro = roffset[idir];
264  // Reuse the result from the previous gridpoint to avoid to many exps:
265  // exp( -a*(x+d)**2) = exp(-a*x**2)*exp(-2*a*x*d)*exp(-a*d**2)
266  // exp(-2*a*(x+d)*d) = exp(-2*a*x*d)*exp(-2*a*d**2)
267  const double t_exp_1 = exp(-zetp * pow(dr, 2));
268  const double t_exp_2 = pow(t_exp_1, 2);
269  double t_exp_min_1 = exp(-zetp * pow(+dr - ro, 2));
270  double t_exp_min_2 = exp(-2 * zetp * (+dr - ro) * (-dr));
271  for (int ig = 0; ig >= lb_cube[idir]; ig--) {
272  const double rpg = ig * dr - ro;
273  t_exp_min_1 *= t_exp_min_2 * t_exp_1;
274  t_exp_min_2 *= t_exp_2;
275  double pg = t_exp_min_1;
276  for (int icoef = 0; icoef <= lp; icoef++) {
277  pol_mutable[idir][icoef][ig + cmax] = pg; // exp(-zetp*rpg**2)
278  pg *= rpg;
279  }
280  }
281  double t_exp_plus_1 = exp(-zetp * pow(-ro, 2));
282  double t_exp_plus_2 = exp(-2 * zetp * (-ro) * (+dr));
283  for (int ig = 0; ig >= lb_cube[idir]; ig--) {
284  const double rpg = (1 - ig) * dr - ro;
285  t_exp_plus_1 *= t_exp_plus_2 * t_exp_1;
286  t_exp_plus_2 *= t_exp_2;
287  double pg = t_exp_plus_1;
288  for (int icoef = 0; icoef <= lp; icoef++) {
289  pol_mutable[idir][icoef][1 - ig + cmax] = pg; // exp(-zetp*rpg**2)
290  pg *= rpg;
291  }
292  }
293  }
294  const double(*pol)[lp + 1][2 * cmax + 1] =
295  (const double(*)[lp + 1][2 * cmax + 1]) pol_mutable;
296 
297  // Precompute mapping from cube to grid indices for each direction
298  int map_mutable[3][2 * cmax + 1];
299  for (int i = 0; i < 3; i++) {
300  for (int k = -cmax; k <= +cmax; k++) {
301  map_mutable[i][k + cmax] =
302  modulo(cubecenter[i] + k - shift_local[i], npts_global[i]);
303  }
304  }
305  const int(*map)[2 * cmax + 1] = (const int(*)[2 * cmax + 1]) map_mutable;
306 
307  // Loop over k dimension of the cube.
308  const int kstart = (int)ceil(-1e-8 - disr_radius * dh_inv[2][2]);
309  const size_t cxy_size = (lp + 1) * (lp + 1) * 2;
310  double cxy[cxy_size];
311  for (int k1 = kstart; k1 <= 0; k1++) {
312  const int k2 = 1 - k1;
313  memset(cxy, 0, cxy_size * sizeof(double));
314 
315 #if (GRID_DO_COLLOCATE)
316  // collocate
317  ortho_cxyz_to_cxy(lp, k1, k2, cmax, pol, cxyz, cxy);
318  ortho_cxy_to_grid(lp, k1, k2, cmax, pol, map, dh, dh_inv, disr_radius,
319  npts_local, cxy, grid);
320 #else
321  // integrate
322  ortho_cxy_to_grid(lp, k1, k2, cmax, pol, map, dh, dh_inv, disr_radius,
323  npts_local, cxy, grid);
324  ortho_cxyz_to_cxy(lp, k1, k2, cmax, pol, cxyz, cxy);
325 #endif
326  }
327 }
328 
329 /*******************************************************************************
330  * \brief Collocates coefficients C_i onto the grid for general case.
331  * \author Ole Schuett
332  ******************************************************************************/
333 static inline void
334 general_ci_to_grid(const int lp, const int jg, const int kg, const int ismin,
335  const int ismax, const int npts_local[3],
336  const int index_min[3], const int index_max[3],
337  const int map_i[], const double gp[3], const int k,
338  const int j, const double exp_ij[], const double exp_jk[],
339  const double exp_ki[], GRID_CONST_WHEN_COLLOCATE double *ci,
341 
342  const int base = kg * npts_local[1] * npts_local[0] + jg * npts_local[0];
343 
344  for (int i = ismin; i <= ismax; i++) {
345  const int ig = map_i[i - index_min[0]];
346  if (ig < 0) {
347  continue; // skip over out-of-bounds indicies
348  }
349  const double di = i - gp[0];
350 
351  const int stride_i = index_max[0] - index_min[0] + 1;
352  const int stride_j = index_max[1] - index_min[1] + 1;
353  const int stride_k = index_max[2] - index_min[2] + 1;
354  const int idx_ij = (j - index_min[1]) * stride_i + i - index_min[0];
355  const int idx_jk = (k - index_min[2]) * stride_j + j - index_min[1];
356  const int idx_ki = (i - index_min[0]) * stride_k + k - index_min[2];
357 
358  // Mathieu's trick: Calculate 3D Gaussian from three precomputed 2D tables
359  //
360  // r = (i-gp[0])*dh[0,:] + (j-gp[1])*dh[1,:] + (k-gp[2])*dh[2,:]
361  // = a + b + c
362  //
363  // r**2 = (a + b + c)**2 = a**2 + b**2 + c**2 + 2ab + 2bc + 2ca
364  //
365  // exp(-r**2) = exp(-a(a+2b)) * exp(-b*(b+2c)) * exp(-c*(c+2a))
366  //
367  const double gaussian = exp_ij[idx_ij] * exp_jk[idx_jk] * exp_ki[idx_ki];
368 
369  const int grid_index = base + ig; // [kg, jg, ig]
370  double dip = gaussian;
371 
372 #if (GRID_DO_COLLOCATE)
373  // collocate
374  double reg = 0.0;
375  for (int il = 0; il <= lp; il++) {
376  reg += ci[il] * dip;
377  dip *= di;
378  }
379  grid[grid_index] += reg;
380 #else
381  // integrate
382  const double reg = grid[grid_index];
383  for (int il = 0; il <= lp; il++) {
384  ci[il] += reg * dip;
385  dip *= di;
386  }
387 #endif
388  }
389 }
390 
391 /*******************************************************************************
392  * \brief Transforms coefficients C_ij into C_i by fixing grid index j.
393  * \author Ole Schuett
394  ******************************************************************************/
395 static inline void general_cij_to_ci(const int lp, const double dj,
396  GRID_CONST_WHEN_COLLOCATE double *cij,
397  GRID_CONST_WHEN_INTEGRATE double *ci) {
398  double djp = 1.0;
399  for (int jl = 0; jl <= lp; jl++) {
400  for (int il = 0; il <= lp - jl; il++) {
401  const int cij_index = jl * (lp + 1) + il; // [jl, il]
402 #if (GRID_DO_COLLOCATE)
403  ci[il] += cij[cij_index] * djp; // collocate
404 #else
405  cij[cij_index] += ci[il] * djp; // integrate
406 #endif
407  }
408  djp *= dj;
409  }
410 }
411 
412 /*******************************************************************************
413  * \brief Collocates coefficients C_ij onto the grid for general case.
414  * \author Ole Schuett
415  ******************************************************************************/
416 static inline void general_cij_to_grid(
417  const int lp, const int k, const int kg, const int npts_local[3],
418  const int index_min[3], const int index_max[3], const int map_i[],
419  const int map_j[], const double dh[3][3], const double gp[3],
420  const double radius, const double exp_ij[], const double exp_jk[],
421  const double exp_ki[], GRID_CONST_WHEN_COLLOCATE double *cij,
423 
424  for (int j = index_min[1]; j <= index_max[1]; j++) {
425  const int jg = map_j[j - index_min[1]];
426  if (jg < 0) {
427  continue; // skip over out-of-bounds indicies
428  }
429  const double dj = j - gp[1];
430 
431  //--------------------------------------------------------------------
432  // Find bounds for the inner loop based on a quadratic equation in i.
433  //
434  // The real-space vector from the center of the gaussian to the
435  // grid point i,j,k is given by:
436  // r = (i-gp[0])*dh[0,:] + (j-gp[1])*dh[1,:] + (k-gp[2])*dh[2,:]
437  //
438  // Separating the term that depends on i:
439  // r = i*dh[0,:] - gp[0]*dh[0,:] + (j-gp[1])*dh[1,:] + (k-gp[2])*dh[2,:]
440  // = i*dh[0,:] + v
441  //
442  // The squared distance works out to:
443  // r**2 = dh[0,:]**2 * i**2 + 2 * v * dh[0,:] * i + v**2
444  // = a * i**2 + b * i + c
445  //
446  // Solving r**2==radius**2 for i yields:
447  // d = b**2 - 4 * a * (c - radius**2)
448  // i = (-b \pm sqrt(d)) / (2*a)
449  //
450  double a = 0.0, b = 0.0, c = 0.0;
451  for (int i = 0; i < 3; i++) {
452  const double v = (0 - gp[0]) * dh[0][i] + (j - gp[1]) * dh[1][i] +
453  (k - gp[2]) * dh[2][i];
454  a += dh[0][i] * dh[0][i];
455  b += 2.0 * v * dh[0][i];
456  c += v * v;
457  }
458  const double d = b * b - 4.0 * a * (c - radius * radius);
459  if (0.0 < d) {
460  const double sqrt_d = sqrt(d);
461  const double inv_2a = 1.0 / (2.0 * a);
462  const int ismin = (int)ceil((-b - sqrt_d) * inv_2a);
463  const int ismax = (int)floor((-b + sqrt_d) * inv_2a);
464 
465  double ci[lp + 1];
466  memset(ci, 0, sizeof(ci));
467 
468 #if (GRID_DO_COLLOCATE)
469  // collocate
470  general_cij_to_ci(lp, dj, cij, ci);
471  general_ci_to_grid(lp, jg, kg, ismin, ismax, npts_local, index_min,
472  index_max, map_i, gp, k, j, exp_ij, exp_jk, exp_ki, ci,
473  grid);
474 #else
475  // integrate
476  general_ci_to_grid(lp, jg, kg, ismin, ismax, npts_local, index_min,
477  index_max, map_i, gp, k, j, exp_ij, exp_jk, exp_ki, ci,
478  grid);
479  general_cij_to_ci(lp, dj, cij, ci);
480 #endif
481  }
482  }
483 }
484 
485 /*******************************************************************************
486  * \brief Transforms coefficients C_ijk into C_ij by fixing grid index k.
487  * \author Ole Schuett
488  ******************************************************************************/
489 static inline void general_cijk_to_cij(const int lp, const double dk,
490  GRID_CONST_WHEN_COLLOCATE double *cijk,
491  GRID_CONST_WHEN_INTEGRATE double *cij) {
492  double dkp = 1.0;
493  for (int kl = 0; kl <= lp; kl++) {
494  for (int jl = 0; jl <= lp - kl; jl++) {
495  for (int il = 0; il <= lp - kl - jl; il++) {
496  const int cij_index = jl * (lp + 1) + il; // [jl, il]
497  const int cijk_index =
498  kl * (lp + 1) * (lp + 1) + jl * (lp + 1) + il; // [kl, jl, il]
499 #if (GRID_DO_COLLOCATE)
500  cij[cij_index] += cijk[cijk_index] * dkp; // collocate
501 #else
502  cijk[cijk_index] += cij[cij_index] * dkp; // integrate
503 #endif
504  }
505  }
506  dkp *= dk;
507  }
508 }
509 
510 /*******************************************************************************
511  * \brief Precompute mapping of grid indices for general case.
512  * \author Ole Schuett
513  ******************************************************************************/
514 static inline void general_precompute_mapping(const int index_min,
515  const int index_max,
516  const int shift_local,
517  const int npts_global,
518  const int bounds[2], int map[]) {
519 
520  // Precompute mapping from continous grid indices to pbc wraped.
521  for (int k = index_min; k <= index_max; k++) {
522  const int kg = modulo(k - shift_local, npts_global);
523  if (bounds[0] <= kg && kg <= bounds[1]) {
524  map[k - index_min] = kg;
525  } else {
526  map[k - index_min] = INT_MIN; // out of bounds - not mapped
527  }
528  }
529 }
530 
531 /*******************************************************************************
532  * \brief Fill one of the 2D tables that speedup 3D Gaussian (Mathieu's trick).
533  * \author Ole Schuett
534  ******************************************************************************/
535 static inline void
536 general_fill_exp_table(const int idir, const int jdir, const int index_min[3],
537  const int index_max[3], const double zetp,
538  const double dh[3][3], const double gp[3],
539  double exp_table[]) {
540 
541  const int stride_i = index_max[idir] - index_min[idir] + 1;
542  const double h_ii = dh[idir][0] * dh[idir][0] + dh[idir][1] * dh[idir][1] +
543  dh[idir][2] * dh[idir][2];
544  const double h_ij = dh[idir][0] * dh[jdir][0] + dh[idir][1] * dh[jdir][1] +
545  dh[idir][2] * dh[jdir][2];
546 
547  for (int i = index_min[idir]; i <= index_max[idir]; i++) {
548  const double di = i - gp[idir];
549  const double rii = di * di * h_ii;
550  const double rij_unit = di * h_ij;
551  const double exp_ij_unit = exp(-zetp * 2.0 * rij_unit);
552 
553  // compute exponentials symmetrically around cube center
554  const int j_center = (int)gp[jdir];
555  const double dj_center = j_center - gp[jdir];
556  const double rij_center = dj_center * rij_unit;
557  const double exp_ij_center = exp(-zetp * (rii + 2.0 * rij_center));
558 
559  // above center
560  double exp_ij = exp_ij_center;
561  for (int j = j_center; j <= index_max[jdir]; j++) {
562  const int idx = (j - index_min[jdir]) * stride_i + i - index_min[idir];
563  exp_table[idx] = exp_ij; // exp(-zetp * (di*di*h_ii + 2*di*dj*h_ij));
564  exp_ij *= exp_ij_unit;
565  }
566 
567  // below center
568  const double exp_ij_unit_inv = 1.0 / exp_ij_unit;
569  exp_ij = exp_ij_center * exp_ij_unit_inv;
570  for (int j = j_center - 1; j >= index_min[jdir]; j--) {
571  const int idx = (j - index_min[jdir]) * stride_i + i - index_min[idir];
572  exp_table[idx] = exp_ij; // exp(-zetp * (di*di*h_ii + 2*di*dj*h_ij));
573  exp_ij *= exp_ij_unit_inv;
574  }
575  }
576 }
577 
578 /*******************************************************************************
579  * \brief Collocates coefficients C_ijk onto the grid for general case.
580  * \author Ole Schuett
581  ******************************************************************************/
582 static inline void
583 general_cijk_to_grid(const int border_mask, const int lp, const double zetp,
584  const double dh[3][3], const double dh_inv[3][3],
585  const double rp[3], const int npts_global[3],
586  const int npts_local[3], const int shift_local[3],
587  const int border_width[3], const double radius,
588  GRID_CONST_WHEN_COLLOCATE double *cijk,
590 
591  // Default for border_mask == 0.
592  int bounds_i[2] = {0, npts_local[0] - 1};
593  int bounds_j[2] = {0, npts_local[1] - 1};
594  int bounds_k[2] = {0, npts_local[2] - 1};
595 
596  // See also rs_find_node() in task_list_methods.F.
597  // If the bit is set then we need to exclude the border in that direction.
598  if (border_mask & (1 << 0))
599  bounds_i[0] += border_width[0];
600  if (border_mask & (1 << 1))
601  bounds_i[1] -= border_width[0];
602  if (border_mask & (1 << 2))
603  bounds_j[0] += border_width[1];
604  if (border_mask & (1 << 3))
605  bounds_j[1] -= border_width[1];
606  if (border_mask & (1 << 4))
607  bounds_k[0] += border_width[2];
608  if (border_mask & (1 << 5))
609  bounds_k[1] -= border_width[2];
610 
611  // center in grid coords
612  // gp = MATMUL(dh_inv, rp)
613  double gp[3] = {0.0, 0.0, 0.0};
614  for (int i = 0; i < 3; i++) {
615  for (int j = 0; j < 3; j++) {
616  gp[i] += dh_inv[j][i] * rp[j];
617  }
618  }
619 
620  // Get the min max indices that contain at least the cube that contains a
621  // sphere around rp of radius radius if the cell is very non-orthogonal this
622  // implies that many useless points are included this estimate can be improved
623  // (i.e. not box but sphere should be used)
624  int index_min[3] = {INT_MAX, INT_MAX, INT_MAX};
625  int index_max[3] = {INT_MIN, INT_MIN, INT_MIN};
626  for (int i = -1; i <= 1; i++) {
627  for (int j = -1; j <= 1; j++) {
628  for (int k = -1; k <= 1; k++) {
629  const double x = rp[0] + i * radius;
630  const double y = rp[1] + j * radius;
631  const double z = rp[2] + k * radius;
632  for (int idir = 0; idir < 3; idir++) {
633  const double resc =
634  dh_inv[0][idir] * x + dh_inv[1][idir] * y + dh_inv[2][idir] * z;
635  index_min[idir] = imin(index_min[idir], (int)floor(resc));
636  index_max[idir] = imax(index_max[idir], (int)ceil(resc));
637  }
638  }
639  }
640  }
641 
642  // Precompute mappings
643  const int range_i = index_max[0] - index_min[0] + 1;
644  int map_i[range_i];
645  general_precompute_mapping(index_min[0], index_max[0], shift_local[0],
646  npts_global[0], bounds_i, map_i);
647  const int range_j = index_max[1] - index_min[1] + 1;
648  int map_j[range_j];
649  general_precompute_mapping(index_min[1], index_max[1], shift_local[1],
650  npts_global[1], bounds_j, map_j);
651  const int range_k = index_max[2] - index_min[2] + 1;
652  int map_k[range_k];
653  general_precompute_mapping(index_min[2], index_max[2], shift_local[2],
654  npts_global[2], bounds_k, map_k);
655 
656  // Precompute exponentials
657  double exp_ij[range_i * range_j];
658  general_fill_exp_table(0, 1, index_min, index_max, zetp, dh, gp, exp_ij);
659  double exp_jk[range_j * range_k];
660  general_fill_exp_table(1, 2, index_min, index_max, zetp, dh, gp, exp_jk);
661  double exp_ki[range_k * range_i];
662  general_fill_exp_table(2, 0, index_min, index_max, zetp, dh, gp, exp_ki);
663 
664  // go over the grid, but cycle if the point is not within the radius
665  const int cij_size = (lp + 1) * (lp + 1);
666  double cij[cij_size];
667  for (int k = index_min[2]; k <= index_max[2]; k++) {
668  const int kg = map_k[k - index_min[2]];
669  if (kg < bounds_k[0] || bounds_k[1] < kg) {
670  continue; // skip over out-of-bounds indicies
671  }
672  const double dk = k - gp[2];
673 
674  // zero coef_xyt
675  memset(cij, 0, cij_size * sizeof(double));
676 
677 #if (GRID_DO_COLLOCATE)
678  // collocate
679  general_cijk_to_cij(lp, dk, cijk, cij);
680  general_cij_to_grid(lp, k, kg, npts_local, index_min, index_max, map_i,
681  map_j, dh, gp, radius, exp_ij, exp_jk, exp_ki, cij,
682  grid);
683 #else
684  // integrate
685  general_cij_to_grid(lp, k, kg, npts_local, index_min, index_max, map_i,
686  map_j, dh, gp, radius, exp_ij, exp_jk, exp_ki, cij,
687  grid);
688  general_cijk_to_cij(lp, dk, cijk, cij);
689 #endif
690  }
691 }
692 
693 /*******************************************************************************
694  * \brief Transforms coefficients C_xyz into C_ijk.
695  * \author Ole Schuett
696  ******************************************************************************/
697 static inline void
698 general_cxyz_to_cijk(const int lp, const double dh[3][3],
699  GRID_CONST_WHEN_COLLOCATE double *cxyz,
700  GRID_CONST_WHEN_INTEGRATE double *cijk) {
701 
702  // transform P_{lxp,lyp,lzp} into a P_{lip,ljp,lkp} such that
703  // sum_{lxp,lyp,lzp} P_{lxp,lyp,lzp} (x-x_p)**lxp (y-y_p)**lyp (z-z_p)**lzp =
704  // sum_{lip,ljp,lkp} P_{lip,ljp,lkp} (i-i_p)**lip (j-j_p)**ljp (k-k_p)**lkp
705 
706  // transform using multinomials
707  double hmatgridp[lp + 1][3][3];
708  for (int i = 0; i < 3; i++) {
709  for (int j = 0; j < 3; j++) {
710  hmatgridp[0][j][i] = 1.0;
711  for (int k = 1; k <= lp; k++) {
712  hmatgridp[k][j][i] = hmatgridp[k - 1][j][i] * dh[j][i];
713  }
714  }
715  }
716 
717  const int lpx = lp;
718  for (int klx = 0; klx <= lpx; klx++) {
719  for (int jlx = 0; jlx <= lpx - klx; jlx++) {
720  for (int ilx = 0; ilx <= lpx - klx - jlx; ilx++) {
721  const int lx = ilx + jlx + klx;
722  const int lpy = lp - lx;
723  for (int kly = 0; kly <= lpy; kly++) {
724  for (int jly = 0; jly <= lpy - kly; jly++) {
725  for (int ily = 0; ily <= lpy - kly - jly; ily++) {
726  const int ly = ily + jly + kly;
727  const int lpz = lp - lx - ly;
728  for (int klz = 0; klz <= lpz; klz++) {
729  for (int jlz = 0; jlz <= lpz - klz; jlz++) {
730  for (int ilz = 0; ilz <= lpz - klz - jlz; ilz++) {
731  const int lz = ilz + jlz + klz;
732  const int il = ilx + ily + ilz;
733  const int jl = jlx + jly + jlz;
734  const int kl = klx + kly + klz;
735  const int lp1 = lp + 1;
736  const int cijk_index =
737  kl * lp1 * lp1 + jl * lp1 + il; // [kl,jl,il]
738  const int cxyz_index =
739  lz * lp1 * lp1 + ly * lp1 + lx; // [lz,ly,lx]
740  const double p =
741  hmatgridp[ilx][0][0] * hmatgridp[jlx][1][0] *
742  hmatgridp[klx][2][0] * hmatgridp[ily][0][1] *
743  hmatgridp[jly][1][1] * hmatgridp[kly][2][1] *
744  hmatgridp[ilz][0][2] * hmatgridp[jlz][1][2] *
745  hmatgridp[klz][2][2] * fac(lx) * fac(ly) * fac(lz) /
746  (fac(ilx) * fac(ily) * fac(ilz) * fac(jlx) * fac(jly) *
747  fac(jlz) * fac(klx) * fac(kly) * fac(klz));
748 #if (GRID_DO_COLLOCATE)
749  cijk[cijk_index] += cxyz[cxyz_index] * p; // collocate
750 #else
751  cxyz[cxyz_index] += cijk[cijk_index] * p; // integrate
752 #endif
753  }
754  }
755  }
756  }
757  }
758  }
759  }
760  }
761  }
762 }
763 
764 /*******************************************************************************
765  * \brief Collocates coefficients C_xyz onto the grid for general case.
766  * \author Ole Schuett
767  ******************************************************************************/
768 static inline void
769 general_cxyz_to_grid(const int border_mask, const int lp, const double zetp,
770  const double dh[3][3], const double dh_inv[3][3],
771  const double rp[3], const int npts_global[3],
772  const int npts_local[3], const int shift_local[3],
773  const int border_width[3], const double radius,
774  GRID_CONST_WHEN_COLLOCATE double *cxyz,
776 
777  const size_t cijk_size = (lp + 1) * (lp + 1) * (lp + 1);
778  double cijk[cijk_size];
779  memset(cijk, 0, cijk_size * sizeof(double));
780 
781 #if (GRID_DO_COLLOCATE)
782  // collocate
783  general_cxyz_to_cijk(lp, dh, cxyz, cijk);
784  general_cijk_to_grid(border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
785  npts_local, shift_local, border_width, radius, cijk,
786  grid);
787 #else
788  // integrate
789  general_cijk_to_grid(border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
790  npts_local, shift_local, border_width, radius, cijk,
791  grid);
792  general_cxyz_to_cijk(lp, dh, cxyz, cijk);
793 #endif
794 }
795 
796 /*******************************************************************************
797  * \brief Collocates coefficients C_xyz onto the grid.
798  * \author Ole Schuett
799  ******************************************************************************/
800 static inline void
801 cxyz_to_grid(const bool orthorhombic, const int border_mask, const int lp,
802  const double zetp, const double dh[3][3],
803  const double dh_inv[3][3], const double rp[3],
804  const int npts_global[3], const int npts_local[3],
805  const int shift_local[3], const int border_width[3],
806  const double radius, GRID_CONST_WHEN_COLLOCATE double *cxyz,
808 
809  enum grid_library_kernel k;
810  if (orthorhombic && border_mask == 0) {
812  ortho_cxyz_to_grid(lp, zetp, dh, dh_inv, rp, npts_global, npts_local,
813  shift_local, radius, cxyz, grid);
814  } else {
816  general_cxyz_to_grid(border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
817  npts_local, shift_local, border_width, radius, cxyz,
818  grid);
819  }
821 }
822 
823 /*******************************************************************************
824  * \brief Transforms coefficients C_ab into C_xyz.
825  * \author Ole Schuett
826  ******************************************************************************/
827 static inline void cab_to_cxyz(const int la_max, const int la_min,
828  const int lb_max, const int lb_min,
829  const double prefactor, const double ra[3],
830  const double rb[3], const double rp[3],
831  GRID_CONST_WHEN_COLLOCATE double *cab,
832  GRID_CONST_WHEN_INTEGRATE double *cxyz) {
833 
834  // Computes the polynomial expansion coefficients:
835  // (x-a)**lxa (x-b)**lxb -> sum_{ls} alpha(ls,lxa,lxb,1)*(x-p)**ls
836  const int lp = la_max + lb_max;
837  double alpha[3][lb_max + 1][la_max + 1][lp + 1];
838  memset(alpha, 0, 3 * (lb_max + 1) * (la_max + 1) * (lp + 1) * sizeof(double));
839 
840  for (int i = 0; i < 3; i++) {
841  const double drpa = rp[i] - ra[i];
842  const double drpb = rp[i] - rb[i];
843  for (int lxa = 0; lxa <= la_max; lxa++) {
844  for (int lxb = 0; lxb <= lb_max; lxb++) {
845  double binomial_k_lxa = 1.0;
846  double a = 1.0;
847  for (int k = 0; k <= lxa; k++) {
848  double binomial_l_lxb = 1.0;
849  double b = 1.0;
850  for (int l = 0; l <= lxb; l++) {
851  alpha[i][lxb][lxa][lxa - l + lxb - k] +=
852  binomial_k_lxa * binomial_l_lxb * a * b;
853  binomial_l_lxb *= ((double)(lxb - l)) / ((double)(l + 1));
854  b *= drpb;
855  }
856  binomial_k_lxa *= ((double)(lxa - k)) / ((double)(k + 1));
857  a *= drpa;
858  }
859  }
860  }
861  }
862 
863  // *** initialise the coefficient matrix, we transform the sum
864  //
865  // sum_{lxa,lya,lza,lxb,lyb,lzb} P_{lxa,lya,lza,lxb,lyb,lzb} *
866  // (x-a_x)**lxa (y-a_y)**lya (z-a_z)**lza (x-b_x)**lxb (y-a_y)**lya
867  // (z-a_z)**lza
868  //
869  // into
870  //
871  // sum_{lxp,lyp,lzp} P_{lxp,lyp,lzp} (x-p_x)**lxp (y-p_y)**lyp (z-p_z)**lzp
872  //
873  // where p is center of the product gaussian, and lp = la_max + lb_max
874  // (current implementation is l**7)
875  //
876 
877  for (int lzb = 0; lzb <= lb_max; lzb++) {
878  for (int lza = 0; lza <= la_max; lza++) {
879  for (int lyb = 0; lyb <= lb_max - lzb; lyb++) {
880  for (int lya = 0; lya <= la_max - lza; lya++) {
881  const int lxb_min = imax(lb_min - lzb - lyb, 0);
882  const int lxa_min = imax(la_min - lza - lya, 0);
883  for (int lxb = lxb_min; lxb <= lb_max - lzb - lyb; lxb++) {
884  for (int lxa = lxa_min; lxa <= la_max - lza - lya; lxa++) {
885  const int ico = coset(lxa, lya, lza);
886  const int jco = coset(lxb, lyb, lzb);
887  const int cab_index = jco * ncoset(la_max) + ico; // [jco, ico]
888  for (int lzp = 0; lzp <= lza + lzb; lzp++) {
889  for (int lyp = 0; lyp <= lp - lza - lzb; lyp++) {
890  for (int lxp = 0; lxp <= lp - lza - lzb - lyp; lxp++) {
891  const double p = alpha[0][lxb][lxa][lxp] *
892  alpha[1][lyb][lya][lyp] *
893  alpha[2][lzb][lza][lzp] * prefactor;
894  const int lp1 = lp + 1;
895  const int cxyz_index =
896  lzp * lp1 * lp1 + lyp * lp1 + lxp; // [lzp, lyp, lxp]
897 #if (GRID_DO_COLLOCATE)
898  cxyz[cxyz_index] += cab[cab_index] * p; // collocate
899 #else
900  cab[cab_index] += cxyz[cxyz_index] * p; // integrate
901 #endif
902  }
903  }
904  }
905  }
906  }
907  }
908  }
909  }
910  }
911 }
912 
913 /*******************************************************************************
914  * \brief Collocates coefficients C_ab onto the grid.
915  * \author Ole Schuett
916  ******************************************************************************/
917 static inline void
918 cab_to_grid(const bool orthorhombic, const int border_mask, const int la_max,
919  const int la_min, const int lb_max, const int lb_min,
920  const double zeta, const double zetb, const double rscale,
921  const double dh[3][3], const double dh_inv[3][3],
922  const double ra[3], const double rab[3], const int npts_global[3],
923  const int npts_local[3], const int shift_local[3],
924  const int border_width[3], const double radius,
925  GRID_CONST_WHEN_COLLOCATE double *cab,
927 
928  // Check if radius is too small to be mapped onto grid of given resolution.
929  double dh_max = 0.0;
930  for (int i = 0; i < 3; i++) {
931  for (int j = 0; j < 3; j++) {
932  dh_max = fmax(dh_max, fabs(dh[i][j]));
933  }
934  }
935  if (2.0 * radius < dh_max) {
936  return;
937  }
938 
939  const double zetp = zeta + zetb;
940  const double f = zetb / zetp;
941  const double rab2 = rab[0] * rab[0] + rab[1] * rab[1] + rab[2] * rab[2];
942  const double prefactor = rscale * exp(-zeta * f * rab2);
943  double rp[3], rb[3];
944  for (int i = 0; i < 3; i++) {
945  rp[i] = ra[i] + f * rab[i];
946  rb[i] = ra[i] + rab[i];
947  }
948 
949  const int lp = la_max + lb_max;
950  const size_t cxyz_size = (lp + 1) * (lp + 1) * (lp + 1);
951  double cxyz[cxyz_size];
952  memset(cxyz, 0, cxyz_size * sizeof(double));
953 
954 #if (GRID_DO_COLLOCATE)
955  // collocate
956  cab_to_cxyz(la_max, la_min, lb_max, lb_min, prefactor, ra, rb, rp, cab, cxyz);
957  cxyz_to_grid(orthorhombic, border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
958  npts_local, shift_local, border_width, radius, cxyz, grid);
959 #else
960  // integrate
961  cxyz_to_grid(orthorhombic, border_mask, lp, zetp, dh, dh_inv, rp, npts_global,
962  npts_local, shift_local, border_width, radius, cxyz, grid);
963  cab_to_cxyz(la_max, la_min, lb_max, lb_min, prefactor, ra, rb, rp, cab, cxyz);
964 #endif
965 }
966 
967 // EOF
static int imax(int x, int y)
Returns the larger of two given integer (missing from the C standard)
static int imin(int x, int y)
Returns the smaller of two given integer (missing from the C standard)
Definition: dbm_miniapp.c:38
static GRID_HOST_DEVICE int coset(int lx, int ly, int lz)
Maps three angular momentum components to a single zero based index.
Definition: grid_common.h:87
static GRID_HOST_DEVICE int ncoset(const int l)
Number of Cartesian orbitals up to given angular momentum quantum.
Definition: grid_common.h:73
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
Definition: grid_common.h:117
static GRID_HOST_DEVICE double fac(const int i)
Factorial function, e.g. fac(5) = 5! = 120.
Definition: grid_common.h:48
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
Definition: grid_common.h:153
@ GRID_BACKEND_REF
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
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 j1
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 kg2
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 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]
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
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]
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_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.
Definition: grid_library.c:129
grid_library_kernel
Various kernels provided by the grid library.
Definition: grid_library.h:65
@ GRID_INTEGRATE_GENERAL
Definition: grid_library.h:69
@ GRID_COLLOCATE_ORTHO
Definition: grid_library.h:66
@ GRID_COLLOCATE_GENERAL
Definition: grid_library.h:68
@ GRID_INTEGRATE_ORTHO
Definition: grid_library.h:67
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.
#define GRID_CONST_WHEN_COLLOCATE
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.
#define GRID_CONST_WHEN_INTEGRATE
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).
real(dp), dimension(3) c
Definition: ai_eri_debug.F:31
real(dp), dimension(3) a
Definition: ai_eri_debug.F:31
real(dp), dimension(3) d
Definition: ai_eri_debug.F:31
real(dp), dimension(3) b
Definition: ai_eri_debug.F:31
real(dp), dimension(3) p
Definition: ai_eri_debug.F:32
integer, parameter, public gaussian