runner_doiact_vec.c 52.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/*******************************************************************************
 * This file is part of SWIFT.
 * Copyright (c) 2016 James Willis (james.s.willis@durham.ac.uk)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 ******************************************************************************/

/* Config parameters. */
#include "../config.h"

/* This object's header. */
#include "runner_doiact_vec.h"

James Willis's avatar
James Willis committed
26
#ifdef WITH_VECTORIZATION
James Willis's avatar
James Willis committed
27
28
29
/**
 * @brief Compute the vector remainder interactions from the secondary cache.
 *
James Willis's avatar
James Willis committed
30
31
 * @param (return) int_cache secondary cache of interactions between two
 * particles.
James Willis's avatar
James Willis committed
32
 * @param icount Interaction count.
James Willis's avatar
James Willis committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
 * @param (return) rhoSum #vector holding the cumulative sum of the density
 * update on pi.
 * @param (return) rho_dhSum #vector holding the cumulative sum of the density
 * gradient update on pi.
 * @param (return) wcountSum #vector holding the cumulative sum of the wcount
 * update on pi.
 * @param (return) wcount_dhSum #vector holding the cumulative sum of the wcount
 * gradient update on pi.
 * @param (return) div_vSum #vector holding the cumulative sum of the divergence
 * update on pi.
 * @param (return) curlvxSum #vector holding the cumulative sum of the curl of
 * vx update on pi.
 * @param (return) curlvySum #vector holding the cumulative sum of the curl of
 * vy update on pi.
 * @param (return) curlvzSum #vector holding the cumulative sum of the curl of
 * vz update on pi.
James Willis's avatar
James Willis committed
49
50
51
52
 * @param v_hi_inv #vector of 1/h for pi.
 * @param v_vix #vector of x velocity of pi.
 * @param v_viy #vector of y velocity of pi.
 * @param v_viz #vector of z velocity of pi.
James Willis's avatar
James Willis committed
53
54
 * @param (return) icount_align Interaction count after the remainder
 * interactions have been performed, should be a multiple of the vector length.
James Willis's avatar
James Willis committed
55
 */
James Willis's avatar
James Willis committed
56
__attribute__((always_inline)) INLINE static void calcRemInteractions(
57
    struct c2_cache *const int_cache,
James Willis's avatar
James Willis committed
58
59
60
61
    const int icount, vector *rhoSum, vector *rho_dhSum, vector *wcountSum,
    vector *wcount_dhSum, vector *div_vSum, vector *curlvxSum,
    vector *curlvySum, vector *curlvzSum, vector v_hi_inv, vector v_vix,
    vector v_viy, vector v_viz, int *icount_align) {
62
63
64
65
66

#ifdef HAVE_AVX512_F
  KNL_MASK_16 knl_mask, knl_mask2;
#endif
  vector int_mask, int_mask2;
James Willis's avatar
James Willis committed
67
68

  /* Work out the number of remainder interactions and pad secondary cache. */
69
70
71
72
73
74
  *icount_align = icount;
  int rem = icount % (NUM_VEC_PROC * VEC_SIZE);
  if (rem != 0) {
    int pad = (NUM_VEC_PROC * VEC_SIZE) - rem;
    *icount_align += pad;

James Willis's avatar
James Willis committed
75
/* Initialise masks to true. */
76
77
78
79
80
81
82
83
84
#ifdef HAVE_AVX512_F
    knl_mask = 0xFFFF;
    knl_mask2 = 0xFFFF;
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
#else
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
#endif
James Willis's avatar
James Willis committed
85
86
87
    /* Pad secondary cache so that there are no contributions in the interaction
     * function. */
    for (int i = icount; i < *icount_align; i++) {
88
89
90
91
92
93
94
95
      int_cache->mq[i] = 0.f;
      int_cache->r2q[i] = 1.f;
      int_cache->dxq[i] = 0.f;
      int_cache->dyq[i] = 0.f;
      int_cache->dzq[i] = 0.f;
      int_cache->vxq[i] = 0.f;
      int_cache->vyq[i] = 0.f;
      int_cache->vzq[i] = 0.f;
96
97
98
99
100
101
102
    }

    /* Zero parts of mask that represent the padded values.*/
    if (pad < VEC_SIZE) {
#ifdef HAVE_AVX512_F
      knl_mask2 = knl_mask2 >> pad;
#else
James Willis's avatar
James Willis committed
103
      for (int i = VEC_SIZE - pad; i < VEC_SIZE; i++) int_mask2.i[i] = 0;
104
#endif
James Willis's avatar
James Willis committed
105
    } else {
106
107
108
109
#ifdef HAVE_AVX512_F
      knl_mask = knl_mask >> (VEC_SIZE - rem);
      knl_mask2 = 0;
#else
James Willis's avatar
James Willis committed
110
      for (int i = rem; i < VEC_SIZE; i++) int_mask.i[i] = 0;
111
112
113
114
      int_mask2.v = vec_setzero();
#endif
    }

James Willis's avatar
James Willis committed
115
116
    /* Perform remainder interaction and remove remainder from aligned
     * interaction count. */
117
    *icount_align = icount - rem;
James Willis's avatar
James Willis committed
118
119
120
121
122
123
124
125
    runner_iact_nonsym_2_vec_density(
        &int_cache->r2q[*icount_align], &int_cache->dxq[*icount_align],
        &int_cache->dyq[*icount_align], &int_cache->dzq[*icount_align],
        v_hi_inv, v_vix, v_viy, v_viz, &int_cache->vxq[*icount_align],
        &int_cache->vyq[*icount_align], &int_cache->vzq[*icount_align],
        &int_cache->mq[*icount_align], rhoSum, rho_dhSum, wcountSum,
        wcount_dhSum, div_vSum, curlvxSum, curlvySum, curlvzSum, int_mask,
        int_mask2,
126
#ifdef HAVE_AVX512_F
James Willis's avatar
James Willis committed
127
        knl_mask, knl_mask2);
128
#else
James Willis's avatar
James Willis committed
129
        0, 0);
130
131
132
133
#endif
  }
}

James Willis's avatar
James Willis committed
134
/**
James Willis's avatar
James Willis committed
135
136
 * @brief Left-packs the values needed by an interaction into the secondary
 * cache (Supports AVX, AVX2 and AVX512 instruction sets).
James Willis's avatar
James Willis committed
137
138
139
140
141
142
143
144
145
146
147
 *
 * @param mask Contains which particles need to interact.
 * @param v_r2 #vector of the separation between two particles squared.
 * @param v_dx #vector of the x separation between two particles.
 * @param v_dy #vector of the y separation between two particles.
 * @param v_dz #vector of the z separation between two particles.
 * @param v_mj #vector of the mass of particle pj.
 * @param v_vjx #vector of x velocity of pj.
 * @param v_vjy #vector of y velocity of pj.
 * @param v_vjz #vector of z velocity of pj.
 * @param cell_cache #cache of all particles in the cell.
James Willis's avatar
James Willis committed
148
149
 * @param (return) int_cache secondary cache of interactions between two
 * particles.
James Willis's avatar
James Willis committed
150
151
 * @param icount Interaction count.
 * @param rhoSum #vector holding the cumulative sum of the density update on pi.
James Willis's avatar
James Willis committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
 * @param rho_dhSum #vector holding the cumulative sum of the density gradient
 * update on pi.
 * @param wcountSum #vector holding the cumulative sum of the wcount update on
 * pi.
 * @param wcount_dhSum #vector holding the cumulative sum of the wcount gradient
 * update on pi.
 * @param div_vSum #vector holding the cumulative sum of the divergence update
 * on pi.
 * @param curlvxSum #vector holding the cumulative sum of the curl of vx update
 * on pi.
 * @param curlvySum #vector holding the cumulative sum of the curl of vy update
 * on pi.
 * @param curlvzSum #vector holding the cumulative sum of the curl of vz update
 * on pi.
James Willis's avatar
James Willis committed
166
167
168
169
170
 * @param v_hi_inv #vector of 1/h for pi.
 * @param v_vix #vector of x velocity of pi.
 * @param v_viy #vector of y velocity of pi.
 * @param v_viz #vector of z velocity of pi.
 */
James Willis's avatar
James Willis committed
171
172
173
174
175
176
177
178
179
180
181
__attribute__((always_inline)) INLINE static void storeInteractions(
    const int mask, const int pjd, vector *v_r2, vector *v_dx, vector *v_dy,
    vector *v_dz, vector *v_mj, vector *v_vjx, vector *v_vjy, vector *v_vjz,
    const struct cache *const cell_cache, struct c2_cache *const int_cache,
    int *icount, vector *rhoSum, vector *rho_dhSum, vector *wcountSum,
    vector *wcount_dhSum, vector *div_vSum, vector *curlvxSum,
    vector *curlvySum, vector *curlvzSum, vector v_hi_inv, vector v_vix,
    vector v_viy, vector v_viz) {

/* Left-pack values needed into the secondary cache using the interaction mask.
 */
182
183
184
185
186
#if defined(HAVE_AVX2) || defined(HAVE_AVX512_F)
  int pack = 0;

#ifdef HAVE_AVX512_F
  pack += __builtin_popcount(mask);
James Willis's avatar
James Willis committed
187
188
189
190
191
192
193
194
  VEC_LEFT_PACK(v_r2->v, mask, &int_cache->r2q[*icount]);
  VEC_LEFT_PACK(v_dx->v, mask, &int_cache->dxq[*icount]);
  VEC_LEFT_PACK(v_dy->v, mask, &int_cache->dyq[*icount]);
  VEC_LEFT_PACK(v_dz->v, mask, &int_cache->dzq[*icount]);
  VEC_LEFT_PACK(v_mj->v, mask, &int_cache->mq[*icount]);
  VEC_LEFT_PACK(v_vjx->v, mask, &int_cache->vxq[*icount]);
  VEC_LEFT_PACK(v_vjy->v, mask, &int_cache->vyq[*icount]);
  VEC_LEFT_PACK(v_vjz->v, mask, &int_cache->vzq[*icount]);
195
196
#else
  vector v_mask;
James Willis's avatar
James Willis committed
197
198
199
200
201
202
203
204
205
206
  VEC_FORM_PACKED_MASK(mask, v_mask.m, pack);

  VEC_LEFT_PACK(v_r2->v, v_mask.m, &int_cache->r2q[*icount]);
  VEC_LEFT_PACK(v_dx->v, v_mask.m, &int_cache->dxq[*icount]);
  VEC_LEFT_PACK(v_dy->v, v_mask.m, &int_cache->dyq[*icount]);
  VEC_LEFT_PACK(v_dz->v, v_mask.m, &int_cache->dzq[*icount]);
  VEC_LEFT_PACK(v_mj->v, v_mask.m, &int_cache->mq[*icount]);
  VEC_LEFT_PACK(v_vjx->v, v_mask.m, &int_cache->vxq[*icount]);
  VEC_LEFT_PACK(v_vjy->v, v_mask.m, &int_cache->vyq[*icount]);
  VEC_LEFT_PACK(v_vjz->v, v_mask.m, &int_cache->vzq[*icount]);
207

208
#endif /* HAVE_AVX512_F */
209
210
211

  (*icount) += pack;
#else
James Willis's avatar
James Willis committed
212
  /* Quicker to do it serially in AVX rather than use intrinsics. */
James Willis's avatar
James Willis committed
213
  for (int bit_index = 0; bit_index < VEC_SIZE; bit_index++) {
214
215
    if (mask & (1 << bit_index)) {
      /* Add this interaction to the queue. */
216
217
218
219
220
221
222
223
      int_cache->r2q[*icount] = v_r2->f[bit_index];
      int_cache->dxq[*icount] = v_dx->f[bit_index];
      int_cache->dyq[*icount] = v_dy->f[bit_index];
      int_cache->dzq[*icount] = v_dz->f[bit_index];
      int_cache->mq[*icount] = cell_cache->m[pjd + bit_index];
      int_cache->vxq[*icount] = cell_cache->vx[pjd + bit_index];
      int_cache->vyq[*icount] = cell_cache->vy[pjd + bit_index];
      int_cache->vzq[*icount] = cell_cache->vz[pjd + bit_index];
224
225
226
227

      (*icount)++;
    }
  }
James Willis's avatar
James Willis committed
228
229
#endif /* defined(HAVE_AVX2) || defined(HAVE_AVX512_F) */

James Willis's avatar
James Willis committed
230
  /* Flush the c2 cache if it has reached capacity. */
James Willis's avatar
James Willis committed
231
  if (*icount >= (C2_CACHE_SIZE - (NUM_VEC_PROC * VEC_SIZE))) {
232
233

    int icount_align = *icount;
James Willis's avatar
James Willis committed
234

James Willis's avatar
James Willis committed
235
    /* Peform remainder interactions. */
236
    calcRemInteractions(int_cache, *icount, rhoSum, rho_dhSum,
James Willis's avatar
James Willis committed
237
238
239
                        wcountSum, wcount_dhSum, div_vSum, curlvxSum, curlvySum,
                        curlvzSum, v_hi_inv, v_vix, v_viy, v_viz,
                        &icount_align);
240
241
242
243

    vector int_mask, int_mask2;
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
James Willis's avatar
James Willis committed
244
245

    /* Perform interactions. */
James Willis's avatar
James Willis committed
246
247
248
249
250
251
252
    for (int pjd = 0; pjd < icount_align; pjd += (NUM_VEC_PROC * VEC_SIZE)) {
      runner_iact_nonsym_2_vec_density(
          &int_cache->r2q[pjd], &int_cache->dxq[pjd], &int_cache->dyq[pjd],
          &int_cache->dzq[pjd], v_hi_inv, v_vix, v_viy, v_viz,
          &int_cache->vxq[pjd], &int_cache->vyq[pjd], &int_cache->vzq[pjd],
          &int_cache->mq[pjd], rhoSum, rho_dhSum, wcountSum, wcount_dhSum,
          div_vSum, curlvxSum, curlvySum, curlvzSum, int_mask, int_mask2, 0, 0);
253
    }
James Willis's avatar
James Willis committed
254
255

    /* Reset interaction count. */
256
257
258
259
    *icount = 0;
  }

}
260
#endif /* WITH_VECTORIZATION */ 
261
262

/**
James Willis's avatar
James Willis committed
263
264
 * @brief Compute the cell self-interaction (non-symmetric) using vector
 * intrinsics with one particle pi at a time.
265
266
267
268
 *
 * @param r The #runner.
 * @param c The #cell.
 */
James Willis's avatar
James Willis committed
269
270
__attribute__((always_inline)) INLINE void runner_doself1_density_vec(
    struct runner *r, struct cell *restrict c) {
271
272
273
274
275
276
277
278
279
280

#ifdef WITH_VECTORIZATION
  const int ti_current = r->e->ti_current;
  int doi_mask;
  struct part *restrict pi;
  int count_align;
  int num_vec_proc = NUM_VEC_PROC;

  struct part *restrict parts = c->parts;
  const int count = c->count;
James Willis's avatar
James Willis committed
281

282
283
  vector v_hi, v_vix, v_viy, v_viz, v_hig2, v_r2;

James Willis's avatar
James Willis committed
284
  TIMER_TIC
285
286
287
288

  if (c->ti_end_min > ti_current) return;
  if (c->ti_end_max < ti_current) error("Cell in an impossible time-zone");

James Willis's avatar
James Willis committed
289
  /* Get the particle cache from the runner and re-allocate
290
291
   * the cache if it is not big enough for the cell. */
  struct cache *restrict cell_cache = &r->par_cache;
James Willis's avatar
James Willis committed
292
293
294

  if (cell_cache->count < count) {
    cache_init(cell_cache, count);
295
296
  }

James Willis's avatar
James Willis committed
297
  /* Read the particles from the cell and store them locally in the cache. */
James Willis's avatar
James Willis committed
298
  cache_read_particles(c, cell_cache);
299
300
301
302

  /* Create secondary cache to store particle interactions. */
  struct c2_cache int_cache;
  int icount = 0, icount_align = 0;
303
304
305
306
307
308
309
310
311
312
313
314
315
316

  /* Loop over the particles in the cell. */
  for (int pid = 0; pid < count; pid++) {

    /* Get a pointer to the ith particle. */
    pi = &parts[pid];

    /* Is the ith particle active? */
    if (pi->ti_end > ti_current) continue;

    vector pix, piy, piz;

    const float hi = cell_cache->h[pid];

James Willis's avatar
James Willis committed
317
    /* Fill particle pi vectors. */
318
319
320
321
322
323
324
325
326
327
328
    pix.v = vec_set1(cell_cache->x[pid]);
    piy.v = vec_set1(cell_cache->y[pid]);
    piz.v = vec_set1(cell_cache->z[pid]);
    v_hi.v = vec_set1(hi);
    v_vix.v = vec_set1(cell_cache->vx[pid]);
    v_viy.v = vec_set1(cell_cache->vy[pid]);
    v_viz.v = vec_set1(cell_cache->vz[pid]);

    const float hig2 = hi * hi * kernel_gamma2;
    v_hig2.v = vec_set1(hig2);

James Willis's avatar
James Willis committed
329
    /* Reset cumulative sums of update vectors. */
James Willis's avatar
James Willis committed
330
331
332
    vector rhoSum, rho_dhSum, wcountSum, wcount_dhSum, div_vSum, curlvxSum,
        curlvySum, curlvzSum;

James Willis's avatar
James Willis committed
333
    /* Get the inverse of hi. */
334
    vector v_hi_inv;
James Willis's avatar
James Willis committed
335

336
    v_hi_inv = vec_reciprocal(v_hi);
James Willis's avatar
James Willis committed
337

338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    rhoSum.v = vec_setzero();
    rho_dhSum.v = vec_setzero();
    wcountSum.v = vec_setzero();
    wcount_dhSum.v = vec_setzero();
    div_vSum.v = vec_setzero();
    curlvxSum.v = vec_setzero();
    curlvySum.v = vec_setzero();
    curlvzSum.v = vec_setzero();

    /* Pad cache if there is a serial remainder. */
    count_align = count;
    int rem = count % (num_vec_proc * VEC_SIZE);
    if (rem != 0) {
      int pad = (num_vec_proc * VEC_SIZE) - rem;

      count_align += pad;
James Willis's avatar
James Willis committed
354
355
356
      /* Set positions to the same as particle pi so when the r2 > 0 mask is
       * applied these extra contributions are masked out.*/
      for (int i = count; i < count_align; i++) {
357
358
359
360
361
362
363
364
365
366
367
        cell_cache->x[i] = pix.f[0];
        cell_cache->y[i] = piy.f[0];
        cell_cache->z[i] = piz.f[0];
      }
    }

    vector pjx, pjy, pjz;
    vector pjvx, pjvy, pjvz, mj;
    vector pjx2, pjy2, pjz2;
    vector pjvx2, pjvy2, pjvz2, mj2;

James Willis's avatar
James Willis committed
368
369
    /* Find all of particle pi's interacions and store needed values in the
     * secondary cache.*/
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    for (int pjd = 0; pjd < count_align; pjd += (num_vec_proc * VEC_SIZE)) {

      /* Load 2 sets of vectors from the particle cache. */
      pjx.v = vec_load(&cell_cache->x[pjd]);
      pjy.v = vec_load(&cell_cache->y[pjd]);
      pjz.v = vec_load(&cell_cache->z[pjd]);
      pjvx.v = vec_load(&cell_cache->vx[pjd]);
      pjvy.v = vec_load(&cell_cache->vy[pjd]);
      pjvz.v = vec_load(&cell_cache->vz[pjd]);
      mj.v = vec_load(&cell_cache->m[pjd]);

      pjx2.v = vec_load(&cell_cache->x[pjd + VEC_SIZE]);
      pjy2.v = vec_load(&cell_cache->y[pjd + VEC_SIZE]);
      pjz2.v = vec_load(&cell_cache->z[pjd + VEC_SIZE]);
      pjvx2.v = vec_load(&cell_cache->vx[pjd + VEC_SIZE]);
      pjvy2.v = vec_load(&cell_cache->vy[pjd + VEC_SIZE]);
      pjvz2.v = vec_load(&cell_cache->vz[pjd + VEC_SIZE]);
387
      mj2.v = vec_load(&cell_cache->m[pjd + VEC_SIZE]);
388
389
390
391
392

      /* Compute the pairwise distance. */
      vector v_dx_tmp, v_dy_tmp, v_dz_tmp;
      vector v_dx_tmp2, v_dy_tmp2, v_dz_tmp2, v_r2_2;

James Willis's avatar
James Willis committed
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
      v_dx_tmp.v = vec_sub(pix.v, pjx.v);
      v_dy_tmp.v = vec_sub(piy.v, pjy.v);
      v_dz_tmp.v = vec_sub(piz.v, pjz.v);
      v_dx_tmp2.v = vec_sub(pix.v, pjx2.v);
      v_dy_tmp2.v = vec_sub(piy.v, pjy2.v);
      v_dz_tmp2.v = vec_sub(piz.v, pjz2.v);

      v_r2.v = vec_mul(v_dx_tmp.v, v_dx_tmp.v);
      v_r2.v = vec_fma(v_dy_tmp.v, v_dy_tmp.v, v_r2.v);
      v_r2.v = vec_fma(v_dz_tmp.v, v_dz_tmp.v, v_r2.v);
      v_r2_2.v = vec_mul(v_dx_tmp2.v, v_dx_tmp2.v);
      v_r2_2.v = vec_fma(v_dy_tmp2.v, v_dy_tmp2.v, v_r2_2.v);
      v_r2_2.v = vec_fma(v_dz_tmp2.v, v_dz_tmp2.v, v_r2_2.v);

/* Form a mask from r2 < hig2 and r2 > 0.*/
408
#ifdef HAVE_AVX512_F
James Willis's avatar
James Willis committed
409
      // KNL_MASK_16 doi_mask, doi_mask_check, doi_mask2, doi_mask2_check;
410
411
      KNL_MASK_16 doi_mask_check, doi_mask2, doi_mask2_check;

James Willis's avatar
James Willis committed
412
      doi_mask_check = vec_cmp_gt(v_r2.v, vec_setzero());
413
414
      doi_mask = vec_cmp_lt(v_r2.v, v_hig2.v);

James Willis's avatar
James Willis committed
415
      doi_mask2_check = vec_cmp_gt(v_r2_2.v, vec_setzero());
416
417
418
419
420
421
422
423
424
      doi_mask2 = vec_cmp_lt(v_r2_2.v, v_hig2.v);

      doi_mask = doi_mask & doi_mask_check;
      doi_mask2 = doi_mask2 & doi_mask2_check;

#else
      vector v_doi_mask, v_doi_mask_check, v_doi_mask2, v_doi_mask2_check;
      int doi_mask2;

James Willis's avatar
James Willis committed
425
      /* Form r2 > 0 mask and r2 < hig2 mask. */
James Willis's avatar
James Willis committed
426
      v_doi_mask_check.v = vec_cmp_gt(v_r2.v, vec_setzero());
427
428
      v_doi_mask.v = vec_cmp_lt(v_r2.v, v_hig2.v);

James Willis's avatar
James Willis committed
429
      /* Form r2 > 0 mask and r2 < hig2 mask. */
James Willis's avatar
James Willis committed
430
      v_doi_mask2_check.v = vec_cmp_gt(v_r2_2.v, vec_setzero());
431
432
      v_doi_mask2.v = vec_cmp_lt(v_r2_2.v, v_hig2.v);

James Willis's avatar
James Willis committed
433
      /* Combine two masks and form integer mask. */
434
435
      doi_mask = vec_cmp_result(vec_and(v_doi_mask.v, v_doi_mask_check.v));
      doi_mask2 = vec_cmp_result(vec_and(v_doi_mask2.v, v_doi_mask2_check.v));
436
#endif /* HAVE_AVX512_F */
437

James Willis's avatar
James Willis committed
438
439
      /* If there are any interactions left pack interaction values into c2
       * cache. */
440
      if (doi_mask) {
James Willis's avatar
James Willis committed
441
442
443
444
445
        storeInteractions(doi_mask, pjd, &v_r2, &v_dx_tmp, &v_dy_tmp, &v_dz_tmp,
                          &mj, &pjvx, &pjvy, &pjvz, cell_cache, &int_cache,
                          &icount, &rhoSum, &rho_dhSum, &wcountSum,
                          &wcount_dhSum, &div_vSum, &curlvxSum, &curlvySum,
                          &curlvzSum, v_hi_inv, v_vix, v_viy, v_viz);
446
447
      }
      if (doi_mask2) {
James Willis's avatar
James Willis committed
448
449
450
451
452
        storeInteractions(
            doi_mask2, pjd + VEC_SIZE, &v_r2_2, &v_dx_tmp2, &v_dy_tmp2,
            &v_dz_tmp2, &mj2, &pjvx2, &pjvy2, &pjvz2, cell_cache, &int_cache,
            &icount, &rhoSum, &rho_dhSum, &wcountSum, &wcount_dhSum, &div_vSum,
            &curlvxSum, &curlvySum, &curlvzSum, v_hi_inv, v_vix, v_viy, v_viz);
453
454
455
      }
    }

James Willis's avatar
James Willis committed
456
    /* Perform padded vector remainder interactions if any are present. */
457
    calcRemInteractions(&int_cache, icount, &rhoSum, &rho_dhSum,
James Willis's avatar
James Willis committed
458
459
460
461
462
463
                        &wcountSum, &wcount_dhSum, &div_vSum, &curlvxSum,
                        &curlvySum, &curlvzSum, v_hi_inv, v_vix, v_viy, v_viz,
                        &icount_align);

    /* Initialise masks to true in case remainder interactions have been
     * performed. */
464
465
466
467
468
469
470
471
472
473
474
475
    vector int_mask, int_mask2;
#ifdef HAVE_AVX512_F
    KNL_MASK_16 knl_mask = 0xFFFF;
    KNL_MASK_16 knl_mask2 = 0xFFFF;
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
#else
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
#endif

    /* Perform interaction with 2 vectors. */
James Willis's avatar
James Willis committed
476
477
478
479
480
481
482
    for (int pjd = 0; pjd < icount_align; pjd += (num_vec_proc * VEC_SIZE)) {
      runner_iact_nonsym_2_vec_density(
          &int_cache.r2q[pjd], &int_cache.dxq[pjd], &int_cache.dyq[pjd],
          &int_cache.dzq[pjd], v_hi_inv, v_vix, v_viy, v_viz,
          &int_cache.vxq[pjd], &int_cache.vyq[pjd], &int_cache.vzq[pjd],
          &int_cache.mq[pjd], &rhoSum, &rho_dhSum, &wcountSum, &wcount_dhSum,
          &div_vSum, &curlvxSum, &curlvySum, &curlvzSum, int_mask, int_mask2,
483
#ifdef HAVE_AVX512_F
James Willis's avatar
James Willis committed
484
          knl_mask, knl_mask2);
485
#else
James Willis's avatar
James Willis committed
486
          0, 0);
487
488
489
#endif
    }

James Willis's avatar
James Willis committed
490
491
492
493
494
495
496
497
498
499
    /* Perform horizontal adds on vector sums and store result in particle pi.
     */
    VEC_HADD(rhoSum, pi->rho);
    VEC_HADD(rho_dhSum, pi->density.rho_dh);
    VEC_HADD(wcountSum, pi->density.wcount);
    VEC_HADD(wcount_dhSum, pi->density.wcount_dh);
    VEC_HADD(div_vSum, pi->density.div_v);
    VEC_HADD(curlvxSum, pi->density.rot_v[0]);
    VEC_HADD(curlvySum, pi->density.rot_v[1]);
    VEC_HADD(curlvzSum, pi->density.rot_v[2]);
500
501
502
503
504

    /* Reset interaction count. */
    icount = 0;
  } /* loop over all particles. */

James Willis's avatar
James Willis committed
505
  TIMER_TOC(timer_doself_density);
506
#endif /* WITH_VECTORIZATION */
507
508
509
}

/**
James Willis's avatar
James Willis committed
510
511
 * @brief Compute the cell self-interaction (non-symmetric) using vector
 * intrinsics with two particle pis at a time.
James Willis's avatar
James Willis committed
512
 * CURRENTLY BROKEN DO NOT USE.
513
514
515
516
 *
 * @param r The #runner.
 * @param c The #cell.
 */
James Willis's avatar
James Willis committed
517
518
__attribute__((always_inline)) INLINE void runner_doself1_density_vec_2(
    struct runner *r, struct cell *restrict c) {
519
520
521
522
523
524
525
526
527
528
529
530

#ifdef WITH_VECTORIZATION
  const int ti_current = r->e->ti_current;
  int doi_mask;
  int doi2_mask;
  struct part *restrict pi;
  struct part *restrict pi2;
  int count_align;

  vector v_hi, v_vix, v_viy, v_viz, v_hig2, v_r2;
  vector v_hi2, v_vix2, v_viy2, v_viz2, v_hig2_2, v2_r2;

James Willis's avatar
James Willis committed
531
  TIMER_TIC
532

James Willis's avatar
James Willis committed
533
  /* TODO: Need to find two active particles, not just one. */
534
535
536
537
538
  if (c->ti_end_min > ti_current) return;
  if (c->ti_end_max < ti_current) error("Cell in an impossible time-zone");

  struct part *restrict parts = c->parts;
  const int count = c->count;
James Willis's avatar
James Willis committed
539
540

  /* Get the particle cache from the runner and re-allocate
James Willis's avatar
James Willis committed
541
   * the cache if it is not big enough for the cell. */
542
543
  struct cache *restrict cell_cache = &r->par_cache;

James Willis's avatar
James Willis committed
544
545
  if (cell_cache->count < count) {
    cache_init(cell_cache, count);
546
547
  }

James Willis's avatar
James Willis committed
548
  /* Read the particles from the cell and store them locally in the cache. */
James Willis's avatar
James Willis committed
549
  cache_read_particles(c, &r->par_cache);
550

James Willis's avatar
James Willis committed
551
  /* Create two secondary caches. */
552
553
  int icount = 0, icount_align = 0;
  struct c2_cache int_cache;
James Willis's avatar
James Willis committed
554

555
556
557
  int icount2 = 0, icount_align2 = 0;
  struct c2_cache int_cache2;

558
  /* Loop over the particles in the cell. */
James Willis's avatar
James Willis committed
559
  for (int pid = 0; pid < count; pid += 2) {
560

James Willis's avatar
James Willis committed
561
    /* Get a pointer to the ith particle and next i particle. */
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
    pi = &parts[pid];
    pi2 = &parts[pid + 1];

    /* Is the ith particle active? */
    if (pi->ti_end > ti_current) continue;

    vector pix, piy, piz;
    vector pix2, piy2, piz2;

    const float hi = cell_cache->h[pid];
    const float hi2 = cell_cache->h[pid + 1];

    /* Fill pi position vector. */
    pix.v = vec_set1(cell_cache->x[pid]);
    piy.v = vec_set1(cell_cache->y[pid]);
    piz.v = vec_set1(cell_cache->z[pid]);
    v_hi.v = vec_set1(hi);
    v_vix.v = vec_set1(cell_cache->vx[pid]);
    v_viy.v = vec_set1(cell_cache->vy[pid]);
    v_viz.v = vec_set1(cell_cache->vz[pid]);

    pix2.v = vec_set1(cell_cache->x[pid + 1]);
    piy2.v = vec_set1(cell_cache->y[pid + 1]);
    piz2.v = vec_set1(cell_cache->z[pid + 1]);
    v_hi2.v = vec_set1(hi2);
    v_vix2.v = vec_set1(cell_cache->vx[pid + 1]);
    v_viy2.v = vec_set1(cell_cache->vy[pid + 1]);
    v_viz2.v = vec_set1(cell_cache->vz[pid + 1]);
James Willis's avatar
James Willis committed
590

591
592
593
594
595
    const float hig2 = hi * hi * kernel_gamma2;
    const float hig2_2 = hi2 * hi2 * kernel_gamma2;
    v_hig2.v = vec_set1(hig2);
    v_hig2_2.v = vec_set1(hig2_2);

James Willis's avatar
James Willis committed
596
597
598
599
600
    vector rhoSum, rho_dhSum, wcountSum, wcount_dhSum, div_vSum, curlvxSum,
        curlvySum, curlvzSum;
    vector rhoSum2, rho_dhSum2, wcountSum2, wcount_dhSum2, div_vSum2,
        curlvxSum2, curlvySum2, curlvzSum2;

601
    vector v_hi_inv, v_hi_inv2;
James Willis's avatar
James Willis committed
602

603
604
    v_hi_inv = vec_reciprocal(v_hi);
    v_hi_inv2 = vec_reciprocal(v_hi2);
James Willis's avatar
James Willis committed
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
    rhoSum.v = vec_setzero();
    rho_dhSum.v = vec_setzero();
    wcountSum.v = vec_setzero();
    wcount_dhSum.v = vec_setzero();
    div_vSum.v = vec_setzero();
    curlvxSum.v = vec_setzero();
    curlvySum.v = vec_setzero();
    curlvzSum.v = vec_setzero();

    rhoSum2.v = vec_setzero();
    rho_dhSum2.v = vec_setzero();
    wcountSum2.v = vec_setzero();
    wcount_dhSum2.v = vec_setzero();
    div_vSum2.v = vec_setzero();
    curlvxSum2.v = vec_setzero();
    curlvySum2.v = vec_setzero();
    curlvzSum2.v = vec_setzero();

    /* Pad cache if there is a serial remainder. */
    count_align = count;
    int rem = count % (NUM_VEC_PROC * VEC_SIZE);
    if (rem != 0) {
      int pad = (NUM_VEC_PROC * VEC_SIZE) - rem;

      count_align += pad;
James Willis's avatar
James Willis committed
631
632
633
      /* Set positions to the same as particle pi so when the r2 > 0 mask is
       * applied these extra contributions are masked out.*/
      for (int i = count; i < count_align; i++) {
634
635
636
637
638
639
640
641
642
643
644
        cell_cache->x[i] = pix.f[0];
        cell_cache->y[i] = piy.f[0];
        cell_cache->z[i] = piz.f[0];
      }
    }

    vector pjx, pjy, pjz;
    vector pjvx, pjvy, pjvz, mj;
    vector pjx2, pjy2, pjz2;
    vector pjvx2, pjvy2, pjvz2, mj2;

James Willis's avatar
James Willis committed
645
646
    /* Find all of particle pi's interacions and store needed values in
     * secondary cache.*/
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
    for (int pjd = 0; pjd < count_align; pjd += (NUM_VEC_PROC * VEC_SIZE)) {

      /* Load 2 sets of vectors from the particle cache. */
      pjx.v = vec_load(&cell_cache->x[pjd]);
      pjy.v = vec_load(&cell_cache->y[pjd]);
      pjz.v = vec_load(&cell_cache->z[pjd]);
      pjvx.v = vec_load(&cell_cache->vx[pjd]);
      pjvy.v = vec_load(&cell_cache->vy[pjd]);
      pjvz.v = vec_load(&cell_cache->vz[pjd]);
      mj.v = vec_load(&cell_cache->m[pjd]);

      pjx2.v = vec_load(&cell_cache->x[pjd + VEC_SIZE]);
      pjy2.v = vec_load(&cell_cache->y[pjd + VEC_SIZE]);
      pjz2.v = vec_load(&cell_cache->z[pjd + VEC_SIZE]);
      pjvx2.v = vec_load(&cell_cache->vx[pjd + VEC_SIZE]);
      pjvy2.v = vec_load(&cell_cache->vy[pjd + VEC_SIZE]);
      pjvz2.v = vec_load(&cell_cache->vz[pjd + VEC_SIZE]);
James Willis's avatar
James Willis committed
664
      mj2.v = vec_load(&cell_cache->m[pjd + VEC_SIZE]);
665
666
667
668
669
670
671

      /* Compute the pairwise distance. */
      vector v_dx_tmp, v_dy_tmp, v_dz_tmp;
      vector v_dx_tmp2, v_dy_tmp2, v_dz_tmp2, v_r2_2;
      vector v_dx2_tmp, v_dy2_tmp, v_dz2_tmp;
      vector v_dx2_tmp2, v_dy2_tmp2, v_dz2_tmp2, v2_r2_2;

James Willis's avatar
James Willis committed
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
      v_dx_tmp.v = vec_sub(pix.v, pjx.v);
      v_dy_tmp.v = vec_sub(piy.v, pjy.v);
      v_dz_tmp.v = vec_sub(piz.v, pjz.v);
      v_dx_tmp2.v = vec_sub(pix.v, pjx2.v);
      v_dy_tmp2.v = vec_sub(piy.v, pjy2.v);
      v_dz_tmp2.v = vec_sub(piz.v, pjz2.v);

      v_dx2_tmp.v = vec_sub(pix2.v, pjx.v);
      v_dy2_tmp.v = vec_sub(piy2.v, pjy.v);
      v_dz2_tmp.v = vec_sub(piz2.v, pjz.v);
      v_dx2_tmp2.v = vec_sub(pix2.v, pjx2.v);
      v_dy2_tmp2.v = vec_sub(piy2.v, pjy2.v);
      v_dz2_tmp2.v = vec_sub(piz2.v, pjz2.v);

      v_r2.v = vec_mul(v_dx_tmp.v, v_dx_tmp.v);
      v_r2.v = vec_fma(v_dy_tmp.v, v_dy_tmp.v, v_r2.v);
      v_r2.v = vec_fma(v_dz_tmp.v, v_dz_tmp.v, v_r2.v);
      v_r2_2.v = vec_mul(v_dx_tmp2.v, v_dx_tmp2.v);
      v_r2_2.v = vec_fma(v_dy_tmp2.v, v_dy_tmp2.v, v_r2_2.v);
      v_r2_2.v = vec_fma(v_dz_tmp2.v, v_dz_tmp2.v, v_r2_2.v);

      v2_r2.v = vec_mul(v_dx2_tmp.v, v_dx2_tmp.v);
      v2_r2.v = vec_fma(v_dy2_tmp.v, v_dy2_tmp.v, v2_r2.v);
      v2_r2.v = vec_fma(v_dz2_tmp.v, v_dz2_tmp.v, v2_r2.v);
      v2_r2_2.v = vec_mul(v_dx2_tmp2.v, v_dx2_tmp2.v);
      v2_r2_2.v = vec_fma(v_dy2_tmp2.v, v_dy2_tmp2.v, v2_r2_2.v);
      v2_r2_2.v = vec_fma(v_dz2_tmp2.v, v_dz2_tmp2.v, v2_r2_2.v);

/* Form a mask from r2 < hig2 and r2 > 0.*/
701
#ifdef HAVE_AVX512_F
James Willis's avatar
James Willis committed
702
      // KNL_MASK_16 doi_mask, doi_mask_check, doi_mask2, doi_mask2_check;
703
704
705
      KNL_MASK_16 doi_mask_check, doi_mask2, doi_mask2_check;
      KNL_MASK_16 doi2_mask_check, doi2_mask2, doi2_mask2_check;

James Willis's avatar
James Willis committed
706
      doi_mask_check = vec_cmp_gt(v_r2.v, vec_setzero());
707
708
      doi_mask = vec_cmp_lt(v_r2.v, v_hig2.v);

James Willis's avatar
James Willis committed
709
      doi2_mask_check = vec_cmp_gt(v2_r2.v, vec_setzero());
710
711
      doi2_mask = vec_cmp_lt(v2_r2.v, v_hig2_2.v);

James Willis's avatar
James Willis committed
712
      doi_mask2_check = vec_cmp_gt(v_r2_2.v, vec_setzero());
713
714
      doi_mask2 = vec_cmp_lt(v_r2_2.v, v_hig2.v);

James Willis's avatar
James Willis committed
715
      doi2_mask2_check = vec_cmp_gt(v2_r2_2.v, vec_setzero());
716
      doi2_mask2 = vec_cmp_lt(v2_r2_2.v, v_hig2_2.v);
James Willis's avatar
James Willis committed
717

718
719
720
721
722
723
724
725
726
727
728
729
      doi_mask = doi_mask & doi_mask_check;
      doi_mask2 = doi_mask2 & doi_mask2_check;

      doi2_mask = doi2_mask & doi2_mask_check;
      doi2_mask2 = doi2_mask2 & doi2_mask2_check;
#else
      vector v_doi_mask, v_doi_mask_check, v_doi_mask2, v_doi_mask2_check;
      int doi_mask2;

      vector v_doi2_mask, v_doi2_mask_check, v_doi2_mask2, v_doi2_mask2_check;
      int doi2_mask2;

James Willis's avatar
James Willis committed
730
      v_doi_mask_check.v = vec_cmp_gt(v_r2.v, vec_setzero());
731
732
      v_doi_mask.v = vec_cmp_lt(v_r2.v, v_hig2.v);

James Willis's avatar
James Willis committed
733
      v_doi2_mask_check.v = vec_cmp_gt(v2_r2.v, vec_setzero());
734
735
      v_doi2_mask.v = vec_cmp_lt(v2_r2.v, v_hig2_2.v);

James Willis's avatar
James Willis committed
736
      v_doi_mask2_check.v = vec_cmp_gt(v_r2_2.v, vec_setzero());
737
738
      v_doi_mask2.v = vec_cmp_lt(v_r2_2.v, v_hig2.v);

James Willis's avatar
James Willis committed
739
      v_doi2_mask2_check.v = vec_cmp_gt(v2_r2_2.v, vec_setzero());
740
741
742
743
744
      v_doi2_mask2.v = vec_cmp_lt(v2_r2_2.v, v_hig2_2.v);

      doi_mask = vec_cmp_result(vec_and(v_doi_mask.v, v_doi_mask_check.v));
      doi_mask2 = vec_cmp_result(vec_and(v_doi_mask2.v, v_doi_mask2_check.v));
      doi2_mask = vec_cmp_result(vec_and(v_doi2_mask.v, v_doi2_mask_check.v));
James Willis's avatar
James Willis committed
745
746
      doi2_mask2 =
          vec_cmp_result(vec_and(v_doi2_mask2.v, v_doi2_mask2_check.v));
747
#endif /* HAVE_AVX512_F */
748
749

      /* Hit or miss? */
James Willis's avatar
James Willis committed
750
751
752
753
754
755
756
757
758
759
760
761
762
      // if (doi_mask) {
      storeInteractions(doi_mask, pjd, &v_r2, &v_dx_tmp, &v_dy_tmp, &v_dz_tmp,
                        &mj, &pjvx, &pjvy, &pjvz, cell_cache, &int_cache,
                        &icount, &rhoSum, &rho_dhSum, &wcountSum, &wcount_dhSum,
                        &div_vSum, &curlvxSum, &curlvySum, &curlvzSum, v_hi_inv,
                        v_vix, v_viy, v_viz);
      //}
      // if (doi2_mask) {
      storeInteractions(
          doi2_mask, pjd, &v2_r2, &v_dx2_tmp, &v_dy2_tmp, &v_dz2_tmp, &mj,
          &pjvx, &pjvy, &pjvz, cell_cache, &int_cache2, &icount2, &rhoSum2,
          &rho_dhSum2, &wcountSum2, &wcount_dhSum2, &div_vSum2, &curlvxSum2,
          &curlvySum2, &curlvzSum2, v_hi_inv2, v_vix2, v_viy2, v_viz2);
763
764
      //}
      /* Hit or miss? */
James Willis's avatar
James Willis committed
765
766
767
768
769
770
      // if (doi_mask2) {
      storeInteractions(doi_mask2, pjd + VEC_SIZE, &v_r2_2, &v_dx_tmp2,
                        &v_dy_tmp2, &v_dz_tmp2, &mj2, &pjvx2, &pjvy2, &pjvz2,
                        cell_cache, &int_cache, &icount, &rhoSum, &rho_dhSum,
                        &wcountSum, &wcount_dhSum, &div_vSum, &curlvxSum,
                        &curlvySum, &curlvzSum, v_hi_inv, v_vix, v_viy, v_viz);
771
      //}
James Willis's avatar
James Willis committed
772
773
774
775
776
777
778
      // if (doi2_mask2) {
      storeInteractions(doi2_mask2, pjd + VEC_SIZE, &v2_r2_2, &v_dx2_tmp2,
                        &v_dy2_tmp2, &v_dz2_tmp2, &mj2, &pjvx2, &pjvy2, &pjvz2,
                        cell_cache, &int_cache2, &icount2, &rhoSum2,
                        &rho_dhSum2, &wcountSum2, &wcount_dhSum2, &div_vSum2,
                        &curlvxSum2, &curlvySum2, &curlvzSum2, v_hi_inv2,
                        v_vix2, v_viy2, v_viz2);
779
780
781
      //}
    }

James Willis's avatar
James Willis committed
782
    /* Perform padded vector remainder interactions if any are present. */
783
    calcRemInteractions(&int_cache, icount, &rhoSum, &rho_dhSum,
James Willis's avatar
James Willis committed
784
785
786
                        &wcountSum, &wcount_dhSum, &div_vSum, &curlvxSum,
                        &curlvySum, &curlvzSum, v_hi_inv, v_vix, v_viy, v_viz,
                        &icount_align);
787

788
    calcRemInteractions(&int_cache2, icount2, &rhoSum2, &rho_dhSum2,
James Willis's avatar
James Willis committed
789
790
791
792
793
794
                        &wcountSum2, &wcount_dhSum2, &div_vSum2, &curlvxSum2,
                        &curlvySum2, &curlvzSum2, v_hi_inv2, v_vix2, v_viy2,
                        v_viz2, &icount_align2);

    /* Initialise masks to true incase remainder interactions have been
     * performed. */
795
796
797
798
799
800
801
802
803
804
805
806
    vector int_mask, int_mask2;
    vector int2_mask, int2_mask2;
#ifdef HAVE_AVX512_F
    KNL_MASK_16 knl_mask = 0xFFFF;
    KNL_MASK_16 knl_mask2 = 0xFFFF;
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
    int2_mask.m = vec_setint1(0xFFFFFFFF);
    int2_mask2.m = vec_setint1(0xFFFFFFFF);
#else
    int_mask.m = vec_setint1(0xFFFFFFFF);
    int_mask2.m = vec_setint1(0xFFFFFFFF);
James Willis's avatar
James Willis committed
807

808
809
810
811
812
    int2_mask.m = vec_setint1(0xFFFFFFFF);
    int2_mask2.m = vec_setint1(0xFFFFFFFF);
#endif

    /* Perform interaction with 2 vectors. */
James Willis's avatar
James Willis committed
813
814
815
816
817
818
819
    for (int pjd = 0; pjd < icount_align; pjd += (NUM_VEC_PROC * VEC_SIZE)) {
      runner_iact_nonsym_2_vec_density(
          &int_cache.r2q[pjd], &int_cache.dxq[pjd], &int_cache.dyq[pjd],
          &int_cache.dzq[pjd], v_hi_inv, v_vix, v_viy, v_viz,
          &int_cache.vxq[pjd], &int_cache.vyq[pjd], &int_cache.vzq[pjd],
          &int_cache.mq[pjd], &rhoSum, &rho_dhSum, &wcountSum, &wcount_dhSum,
          &div_vSum, &curlvxSum, &curlvySum, &curlvzSum, int_mask, int_mask2,
820
#ifdef HAVE_AVX512_F
James Willis's avatar
James Willis committed
821
          knl_mask, knl_mask2);
822
#else
James Willis's avatar
James Willis committed
823
          0, 0);
824
825
826
#endif
    }

James Willis's avatar
James Willis committed
827
828
829
830
831
832
833
834
    for (int pjd = 0; pjd < icount_align2; pjd += (NUM_VEC_PROC * VEC_SIZE)) {
      runner_iact_nonsym_2_vec_density(
          &int_cache2.r2q[pjd], &int_cache2.dxq[pjd], &int_cache2.dyq[pjd],
          &int_cache2.dzq[pjd], v_hi_inv2, v_vix2, v_viy2, v_viz2,
          &int_cache2.vxq[pjd], &int_cache2.vyq[pjd], &int_cache2.vzq[pjd],
          &int_cache2.mq[pjd], &rhoSum2, &rho_dhSum2, &wcountSum2,
          &wcount_dhSum2, &div_vSum2, &curlvxSum2, &curlvySum2, &curlvzSum2,
          int2_mask, int2_mask2,
835
#ifdef HAVE_AVX512_F
James Willis's avatar
James Willis committed
836
          knl_mask, knl_mask2);
837
#else
James Willis's avatar
James Willis committed
838
          0, 0);
839
840
#endif
    }
James Willis's avatar
James Willis committed
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
    /* Perform horizontal adds on vector sums and store result in particle pi.
     */
    VEC_HADD(rhoSum, pi->rho);
    VEC_HADD(rho_dhSum, pi->density.rho_dh);
    VEC_HADD(wcountSum, pi->density.wcount);
    VEC_HADD(wcount_dhSum, pi->density.wcount_dh);
    VEC_HADD(div_vSum, pi->density.div_v);
    VEC_HADD(curlvxSum, pi->density.rot_v[0]);
    VEC_HADD(curlvySum, pi->density.rot_v[1]);
    VEC_HADD(curlvzSum, pi->density.rot_v[2]);

    VEC_HADD(rhoSum2, pi2->rho);
    VEC_HADD(rho_dhSum2, pi2->density.rho_dh);
    VEC_HADD(wcountSum2, pi2->density.wcount);
    VEC_HADD(wcount_dhSum2, pi2->density.wcount_dh);
    VEC_HADD(div_vSum2, pi2->density.div_v);
    VEC_HADD(curlvxSum2, pi2->density.rot_v[0]);
    VEC_HADD(curlvySum2, pi2->density.rot_v[1]);
    VEC_HADD(curlvzSum2, pi2->density.rot_v[2]);
860
861
862
863
864
865

    /* Reset interaction count. */
    icount = 0;
    icount2 = 0;
  } /* loop over all particles. */

James Willis's avatar
James Willis committed
866
  TIMER_TOC(timer_doself_density);
867
#endif /* WITH_VECTORIZATION */
868
}
869
870
871
872
873
874
875
876
877
878
879
880
881

/**
 * @brief Compute the interactions between a cell pair (non-symmetric).
 *
 * @param r The #runner.
 * @param ci The first #cell.
 * @param cj The second #cell.
 */
void runner_dopair1_density_vec(struct runner *r, struct cell *ci, struct cell *cj) {

#ifdef WITH_VECTORIZATION
  const struct engine *restrict e = r->e;

882
  int icount = 0, icount_align = 0;
883
  struct c2_cache int_cache;
884
  int num_vec_proc = 1;
885

James Willis's avatar
James Willis committed
886
  vector v_hi, v_vix, v_viy, v_viz, v_hig2;
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

  TIMER_TIC;

  /* Anything to do here? */
  if (!cell_is_active(ci, e) && !cell_is_active(cj, e)) return;

#ifdef SWIFT_DEBUG_CHECKS
  cell_is_drifted(ci, e);
  cell_is_drifted(cj, e);
#endif

  /* Get the sort ID. */
  double shift[3] = {0.0, 0.0, 0.0};
  const int sid = space_getsid(e->s, &ci, &cj, shift);

  /* Have the cells been sorted? */
  if (!(ci->sorted & (1 << sid)) || !(cj->sorted & (1 << sid)))
    error("Trying to interact unsorted cells.");

  /* Get the cutoff shift. */
  double rshift = 0.0;
  for (int k = 0; k < 3; k++) rshift += shift[k] * runner_shift[sid][k];

  /* Pick-out the sorted lists. */
  const struct entry *restrict sort_i = &ci->sort[sid * (ci->count + 1)];
  const struct entry *restrict sort_j = &cj->sort[sid * (cj->count + 1)];

  /* Get some other useful values. */
  const double hi_max = ci->h_max * kernel_gamma - rshift;
  const double hj_max = cj->h_max * kernel_gamma;
  const int count_i = ci->count;
  const int count_j = cj->count;
  struct part *restrict parts_i = ci->parts;
  struct part *restrict parts_j = cj->parts;
  const double di_max = sort_i[count_i - 1].d - rshift;
  const double dj_min = sort_j[0].d;
  const float dx_max = (ci->dx_max + cj->dx_max);

925
926
927
928
929
930
931
932
933
934
935
  /* Get the particle cache from the runner and re-allocate
   * the cache if it is not big enough for the cell. */
  struct cache *restrict ci_cache = &r->par_cache;

  if (ci_cache->count < count_i) {
    cache_init(ci_cache, count_i);
  }
  if (cj_cache.count < count_j) {
    cache_init(&cj_cache, count_j);
  }

936
937
  //cache_read_two_cells(ci, cj, ci_cache, &cj_cache, shift);
  cache_read_two_cells_sorted(ci, cj, ci_cache, &cj_cache, sort_i, sort_j, shift);
938

939
940
941
942
943
944
945
  /* Loop over the parts in ci. */
  for (int pid = count_i - 1;
       pid >= 0 && sort_i[pid].d + hi_max + dx_max > dj_min; pid--) {

    /* Get a hold of the ith part in ci. */
    struct part *restrict pi = &parts_i[sort_i[pid].i];
    if (!part_is_active(pi, e)) continue;
946

James Willis's avatar
James Willis committed
947
    int ci_cache_idx = pid; //sort_i[pid].i;
948
949

    const float hi = ci_cache->h[ci_cache_idx];
950
951
952
953
954
    const double di = sort_i[pid].d + hi * kernel_gamma + dx_max - rshift;
    if (di < dj_min) continue;

    const float hig2 = hi * hi * kernel_gamma2;

955
    vector pix, piy, piz;
956
957

    /* Fill particle pi vectors. */
958
959
960
    pix.v = vec_set1(ci_cache->x[ci_cache_idx]);
    piy.v = vec_set1(ci_cache->y[ci_cache_idx]);
    piz.v = vec_set1(ci_cache->z[ci_cache_idx]);
961
    v_hi.v = vec_set1(hi);
962
963
964
    v_vix.v = vec_set1(ci_cache->vx[ci_cache_idx]);
    v_viy.v = vec_set1(ci_cache->vy[ci_cache_idx]);
    v_viz.v = vec_set1(ci_cache->vz[ci_cache_idx]);
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985

    v_hig2.v = vec_set1(hig2);

    /* Reset cumulative sums of update vectors. */
    vector rhoSum, rho_dhSum, wcountSum, wcount_dhSum, div_vSum, curlvxSum,
        curlvySum, curlvzSum;

    /* Get the inverse of hi. */
    vector v_hi_inv;

    v_hi_inv = vec_reciprocal(v_hi);

    rhoSum.v = vec_setzero();
    rho_dhSum.v = vec_setzero();
    wcountSum.v = vec_setzero();
    wcount_dhSum.v = vec_setzero();
    div_vSum.v = vec_setzero();
    curlvxSum.v = vec_setzero();
    curlvySum.v = vec_setzero();
    curlvzSum.v = vec_setzero();

986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
    int exit_iteration = count_j;
    for (int pjd = 0; pjd < count_j ; pjd++) {
      if(sort_j[pjd].d >= di) exit_iteration = pjd;
    }

    /* Pad cache if there is a serial remainder. */
    int exit_iteration_align = exit_iteration;
    int rem = exit_iteration % (num_vec_proc * VEC_SIZE);
    if (rem != 0) {
      int pad = (num_vec_proc * VEC_SIZE) - rem;

      exit_iteration_align += pad;
      /* Set positions to the same as particle pi so when the r2 > 0 mask is
       * applied these extra contributions are masked out.*/
      for (int i = exit_iteration; i < exit_iteration_align; i++) {