This file is indexed.

/usr/include/liggghts/region_neighbor_list_I.h is in libliggghts-dev 3.7.0+repack1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
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
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
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
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
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
701
702
703
704
705
706
707
708
709
710
711
712
713
714
/* ----------------------------------------------------------------------
    This is the

    ██╗     ██╗ ██████╗  ██████╗  ██████╗ ██╗  ██╗████████╗███████╗
    ██║     ██║██╔════╝ ██╔════╝ ██╔════╝ ██║  ██║╚══██╔══╝██╔════╝
    ██║     ██║██║  ███╗██║  ███╗██║  ███╗███████║   ██║   ███████╗
    ██║     ██║██║   ██║██║   ██║██║   ██║██╔══██║   ██║   ╚════██║
    ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║  ██║   ██║   ███████║
    ╚══════╝╚═╝ ╚═════╝  ╚═════╝  ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚══════╝®

    DEM simulation engine, released by
    DCS Computing Gmbh, Linz, Austria
    http://www.dcs-computing.com, office@dcs-computing.com

    LIGGGHTS® is part of CFDEM®project:
    http://www.liggghts.com | http://www.cfdem.com

    Core developer and main author:
    Christoph Kloss, christoph.kloss@dcs-computing.com

    LIGGGHTS® is open-source, distributed under the terms of the GNU Public
    License, version 2 or later. It 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. You should have
    received a copy of the GNU General Public License along with LIGGGHTS®.
    If not, see http://www.gnu.org/licenses . See also top-level README
    and LICENSE files.

    LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH,
    the producer of the LIGGGHTS® software and the CFDEM®coupling software
    See http://www.cfdem.com/terms-trademark-policy for details.

-------------------------------------------------------------------------
    Contributing author and copyright for this file:
    (if not contributing author is listed, this file has been contributed
    by the core developer)

    Richard Berger (JKU Linz)
    Christoph Kloss (DCS Computing GmbH)
    Alexander Podlozhnyuk (DCS Computing GmbH)

    Copyright 2014-2015 JKU Linz
    Copyright 2015-     DCS Computing GmbH
------------------------------------------------------------------------- */

static const double SMALL_REGION_NEIGHBOR_LIST = 1.0e-6;
static const double BIG_REGION_NEIGHBOR_LIST = 1.0e20;

/**
 * @brief Default constructor which will create an empty neighbor list
 */
template<bool INTERPOLATE>
RegionNeighborList<INTERPOLATE>::RegionNeighborList(LAMMPS *lmp) :
    IRegionNeighborList(),
    Pointers(lmp),
    ncount(0),
    bbox_set(false)
{
}

/**
 * @brief Determine if the given particle overlaps with any particle in this neighbor list
 * @param x        position of particle to check
 * @param radius   radius of particle to check
 * @return true if particle has an overlap with a particle in this neighbor list, false otherwise
 */
template<bool INTERPOLATE>
bool RegionNeighborList<INTERPOLATE>::hasOverlap(double * x, double radius) const
{
  int ibin = coord2bin(x);

  for(std::vector<int>::const_iterator it = stencil.begin(); it != stencil.end(); ++it)
  {
    const int offset = *it;
    if((ibin+offset < 0) || ((size_t)(ibin+offset) >= bins.size()))
    {
        
        error->one(FLERR,"assertion failed");
    }
    const std::vector<Particle<INTERPOLATE> > & plist = bins[ibin+offset].particles;

    for(typename std::vector<Particle<INTERPOLATE> >::const_iterator pit = plist.begin(); pit != plist.end(); ++pit)
    {
      const Particle<INTERPOLATE> & p = *pit;
      double del[3];
      vectorSubtract3D(x, p.x, del);
      const double rsq = vectorMag3DSquared(del);
      const double radsum = radius + p.radius;
      if (rsq <= radsum*radsum) return true;
    }
  }

  return false;
}

#ifdef SUPERQUADRIC_ACTIVE_FLAG
template<bool INTERPOLATE>
bool RegionNeighborList<INTERPOLATE>::hasOverlap_superquadric(double * x, double radius, double *quaternion, double *shape, double *roundness) const
{
  int ibin = coord2bin(x);

  for(std::vector<int>::const_iterator it = stencil.begin(); it != stencil.end(); ++it) {
    const int offset = *it;
    if((ibin+offset < 0) || ((size_t)(ibin+offset) >= bins.size()))
    {

        error->one(FLERR,"assertion failed");
    }
    const std::vector<Particle<INTERPOLATE> > & plist = bins[ibin+offset].particles;

    Superquadric particle1(x, quaternion, shape, roundness);
    for(typename std::vector<Particle<INTERPOLATE> >::const_iterator pit = plist.begin(); pit != plist.end(); ++pit) {
      const Particle<INTERPOLATE> & p = *pit;
      double del[3];
      vectorSubtract3D(x, p.x, del);
      const double rsq = vectorMag3DSquared(del);
      const double radsum = radius + p.radius;
      if(check_obb_flag) {
        double x_copy[3], quaternion_copy[4], shape_copy[3], roundness_copy[2];
        vectorCopy3D(p.x, x_copy);
        vectorCopy4D(p.quaternion, quaternion_copy);
        vectorCopy3D(p.shape, shape_copy);
        vectorCopy2D(p.roundness, roundness_copy);
        Superquadric particle2(x_copy, quaternion_copy, shape_copy, roundness_copy);
        double contact_point[3];

        if (rsq <= radsum*radsum and (MathExtraLiggghtsNonspherical::capsules_intersect(&particle1, &particle2, contact_point) and
                                      MathExtraLiggghtsNonspherical::obb_intersect(&particle1, &particle2))) {
            return true;
        }
      } else
        if (rsq <= radsum*radsum) return true;
    }
  }

  return false;
}

#endif
/**
 * @brief Determine if the given particle overlaps with any particle in this neighbor list
 * @param x        position of particle to check
 * @param radius   radius of particle to check
 * @param overlap_list  list of overlaps, to be populated by this function
 * @return true if particle has an overlap with a particle in this neighbor list, false otherwise
 */

template<bool INTERPOLATE>
bool RegionNeighborList<INTERPOLATE>::hasOverlapWith(double * x, double radius, std::vector<int> &overlap_list) const
{
  int ibin = coord2bin(x);

  bool overlap = false;

  for(std::vector<int>::const_iterator it = stencil.begin(); it != stencil.end(); ++it)
  {
    const int offset = *it;
    if((ibin+offset < 0) || ((size_t)(ibin+offset) >= bins.size()))
    {
        
        error->one(FLERR,"assertion failed");
    }
    const std::vector<Particle<INTERPOLATE> > & plist = bins[ibin+offset].particles;

    for(typename std::vector<Particle<INTERPOLATE> >::const_iterator pit = plist.begin(); pit != plist.end(); ++pit)
    {
      const Particle<INTERPOLATE> & p = *pit;
      double del[3];
      vectorSubtract3D(x, p.x, del);
      const double rsq = vectorMag3DSquared(del);
      const double radsum = radius + p.radius;
      if (rsq <= radsum*radsum)
      {
        overlap_list.push_back(p.index);
        overlap = true;
      }
    }
  }

  return overlap;
}

/**
 * @brief Insert a new particle into neighbor list
 * @param x        position in 3D
 * @param radius   particle radius
 */
template<bool INTERPOLATE>
void RegionNeighborList<INTERPOLATE>::insert(double * x, double radius,int index)
{
  int quadrant;
  double wx,wy,wz;
  int ibin = coord2bin(x,quadrant,wx,wy,wz);
  if((ibin < 0) || ((size_t)(ibin) >= bins.size()))
  {
      
      error->one(FLERR,"assertion failed");
  }

  bins[ibin].particles.push_back(Particle<INTERPOLATE>(index,x, radius,ibin,quadrant,wx,wy,wz));

  ++ncount;
}

#ifdef SUPERQUADRIC_ACTIVE_FLAG
template<bool INTERPOLATE>
void RegionNeighborList<INTERPOLATE>::insert_superquadric(double * x, double radius, double *quaternion, double *shape, double *roundness, int index) {
  int quadrant;
  double wx,wy,wz;
  int ibin = coord2bin(x,quadrant,wx,wy,wz);
  if((ibin < 0) || ((size_t)(ibin) >= bins.size()))
  {

      error->one(FLERR,"assertion failed");
  }

  bins[ibin].particles.push_back(Particle<INTERPOLATE>(index,x,radius,quaternion, shape, roundness, ibin,quadrant,wx,wy,wz));
  ++ncount;
}
#endif

/**
 * @brief Reset neighbor list and brings it into initial state
 */
template<bool INTERPOLATE>
void RegionNeighborList<INTERPOLATE>::reset()
{
  // reset all the settings from setBoundaryBox
  bins.clear();
  stencil.clear();
  bbox_set = false;
  nbinx = nbiny = nbinz = 0;
  binsizex = binsizey = binsizez = 0;
  bininvx = bininvy = bininvz = 0;
  mbinxlo = mbinylo = mbinzlo = 0;
  mbinx = mbiny = mbinz = 0;

  // reset particle counter
  ncount = 0;
}

/**
 * @brief Return size of buffer for one bin
 *
 * \sa pushBinToBuffer
 */
template<bool INTERPOLATE>
int RegionNeighborList<INTERPOLATE>::getSizeOne() const
{
    return 4;
}

/**
 * @brief Push bin information to buffer
 *
 * \sa getSizeOne
 */
template<bool INTERPOLATE>
int RegionNeighborList<INTERPOLATE>::pushBinToBuffer(int i, double *buf) const
{
    int m = 0;
    buf[m++] = this->bins[i].center[0];
    buf[m++] = this->bins[i].center[1];
    buf[m++] = this->bins[i].center[2];
    buf[m++] = this->bins[i].id;
    return m;
}

/**
 * @brief Clear bins (remove all inserted particles)
 */
template<bool INTERPOLATE>
void RegionNeighborList<INTERPOLATE>::clear()
{
  for(typename std::vector<Bin<INTERPOLATE> >::iterator it = bins.begin(); it != bins.end(); ++it)
  {
    (*it).particles.clear();
  }
  ncount = 0;
}

/**
 * @brief Returns the number of particles inserted into the neighbor list
 * @return number of particles in neighbor list
 */

template<bool INTERPOLATE>
size_t RegionNeighborList<INTERPOLATE>::count() const
{
  return ncount;
}

/**
 * @brief Set or Update the region bounding box
 *
 * This will update internal data structures to ensure they can handle the new
 * region, which is defined by its bounding box.
 *
 * @param bb        bounding box of region
 * @param maxrad    largest particle radius
 * @param extend    enable extending the box for ghost particles
 * @param failsafe  limit max. number of bins
 * @return true if bounding box was set successfully, false bounding box could not
 * be set and neighbor list is not usable
 */

template<bool INTERPOLATE>
inline void RegionNeighborList<INTERPOLATE>::setBoundingBox_calc_interpolation_stencil(Bin<INTERPOLATE> &it,int ibin,int ix,int iy, int iz) const
{

}

template<>
inline void RegionNeighborList<true>::setBoundingBox_calc_interpolation_stencil(Bin<true> &it,int ibin,int ix,int iy, int iz) const
{
        Stencil stencilTmp;

        it.stencils.clear();

        int stencil_shift_up_quadrant = 0;
        int stencil_shift_down_quadrant = 0;
        int ii,jj,kk;
        for(int iquad = 0; iquad < 8; iquad++)
        {
            
            stencil_shift_up_quadrant = 0;
            stencil_shift_down_quadrant = 0;
            const int qx = (iquad & 1) >> 0; // 0 or 1
            const int qy = (iquad & 2) >> 1; // 0 or 1
            const int qz = (iquad & 4) >> 2; // 0 or 1

            if(0 == ix && 0 == qx)
            {
                stencil_shift_up_quadrant |= 1;
                ii = 1;
            }
            else if(ix == (mbinx-1)  && 1 == qx)
            {
                stencil_shift_down_quadrant |= 1;
                ii = -1;
            }
            else
                ii = 0;

            if(0 == iy && 0 == qy)
            {
                stencil_shift_up_quadrant |= 2;
                jj = 1;
            }
            else if(iy == (mbiny-1) && 1 == qy)
            {
                stencil_shift_down_quadrant |= 2;
                jj = -1;
            }
            else
                jj = 0;

            if(0 == iz && 0 == qz)
            {
                stencil_shift_up_quadrant |= 4;
                kk = 1;
            }
            else if(iz == (mbinz-1) && 1 == qz)
            {
                stencil_shift_down_quadrant |= 4;
                kk = -1;
            }
            else
                kk = 0;

            // generate stencil which will look at 8 relevant bins - self + 7 quadrant neighs
            // self can be located anywhere within these 8 bins
            stencilTmp.clear();
            for (int k = -1+qz; k <= qz; k++)
            {
                for (int j = -1+qy; j <= qy; j++)
                {
                    for (int i = -1+qx; i <= qx; i++)
                    {
                        int isubbin = ((iz+k+kk)*mbiny*mbinx + (iy+j+jj)*mbinx + (ix+i+ii));
                        if( isubbin < 0 || isubbin >= mbins())
                            stencilTmp.push_back(-1);
                        else
                            stencilTmp.push_back(isubbin);
                        
                    }
                }
            }

            it.stencils.push_back(stencilTmp);
            
            it.stencil_shift_up.push_back(stencil_shift_up_quadrant);
            it.stencil_shift_down.push_back(stencil_shift_down_quadrant);

        }
}

template<bool INTERPOLATE>
bool RegionNeighborList<INTERPOLATE>::setBoundingBox(BoundingBox & bb, double maxrad, bool extend, bool failsafe)
{
  double extent[3];
  bb.getExtent(extent);

  if(extent[0] <= 0.0 || extent[1] <= 0.0 || extent[2] <= 0.0) {
    // empty or invalid region
    bins.clear();
    stencil.clear();
    return false;
  }

  bb.getBoxBounds(bboxlo, bboxhi);

  // testing code
  double binsize_optimal = 4*maxrad;
  double binsizeinv = 1.0/binsize_optimal;

  // test for too many global bins in any dimension due to huge global domain or small maxrad
  const int max_small_int = std::numeric_limits<int>::max();
  // we may repeat this calculation in case of failsafe
  bool repeat = false;
  bigint bbin = -1; // final number of bins
  double bsubboxlo[3], bsubboxhi[3]; // box bounds
  do
  {
    // create actual bins
    nbinx = static_cast<int>((extent[0]+binsize_optimal*1e-10)*binsizeinv);
    nbiny = static_cast<int>((extent[1]+binsize_optimal*1e-10)*binsizeinv);
    nbinz = static_cast<int>((extent[2]+binsize_optimal*1e-10)*binsizeinv);

    if (nbinx == 0) nbinx = 1;
    if (nbiny == 0) nbiny = 1;
    if (nbinz == 0) nbinz = 1;

    binsizex = extent[0]/nbinx;
    binsizey = extent[1]/nbiny;
    binsizez = extent[2]/nbinz;

    bininvx = 1.0 / binsizex;
    bininvy = 1.0 / binsizey;
    bininvz = 1.0 / binsizez;

    // mbinlo/hi = lowest and highest global bins my ghost atoms could be in
    // coord = lowest and highest values of coords for my ghost atoms
    // static_cast(-1.5) = -1, so subract additional -1
    // add in SMALL for round-off safety
    bb.getBoxBounds(bsubboxlo, bsubboxhi);

    // list is extended for ghost atoms or
    // the list covers just exactly the region
    if (extend)
    {
      double coord = bsubboxlo[0] - SMALL_REGION_NEIGHBOR_LIST*extent[0];
      mbinxlo = static_cast<int> ((coord-bboxlo[0])*bininvx);
      if (coord < bboxlo[0]) mbinxlo = mbinxlo - 1;
      coord = bsubboxhi[0] + SMALL_REGION_NEIGHBOR_LIST*extent[0];
      int mbinxhi = static_cast<int> ((coord-bboxlo[0])*bininvx);

      coord = bsubboxlo[1] - SMALL_REGION_NEIGHBOR_LIST*extent[1];
      mbinylo = static_cast<int> ((coord-bboxlo[1])*bininvy);
      if (coord < bboxlo[1]) mbinylo = mbinylo - 1;
      coord = bsubboxhi[1] + SMALL_REGION_NEIGHBOR_LIST*extent[1];
      int mbinyhi = static_cast<int> ((coord-bboxlo[1])*bininvy);

      coord = bsubboxlo[2] - SMALL_REGION_NEIGHBOR_LIST*extent[2];
      mbinzlo = static_cast<int> ((coord-bboxlo[2])*bininvz);
      if (coord < bboxlo[2]) mbinzlo = mbinzlo - 1;
      coord = bsubboxhi[2] + SMALL_REGION_NEIGHBOR_LIST*extent[2];
      int mbinzhi = static_cast<int> ((coord-bboxlo[2])*bininvz);

      // extend bins by 1 to insure stencil extent is included

      mbinxlo = mbinxlo - 1;
      mbinxhi = mbinxhi + 1;
      mbinylo = mbinylo - 1;
      mbinyhi = mbinyhi + 1;
      mbinzlo = mbinzlo - 1;
      mbinzhi = mbinzhi + 1;

      mbinx = mbinxhi - mbinxlo + 1;
      mbiny = mbinyhi - mbinylo + 1;
      mbinz = mbinzhi - mbinzlo + 1;

    }
    else
    {
      mbinxlo = mbinylo = mbinzlo = 0;
      mbinx = nbinx;
      mbiny = nbiny;
      mbinz = nbinz;

    }

    // final check of number of bins
    bbin = ((bigint) mbinx) * ((bigint) mbiny) * ((bigint) mbinz);

    if (bbin > max_small_int) { // too many bins
      // check for failsafe mode
      // check for repeat - ensure that we run the loop only once!
      if(failsafe && !repeat)
      {
        binsizeinv = 1./ (vectorMax3D(extent) / 100.);
        repeat = true;
      } else {
        printf("ERROR: Too many neighbor bins\n");
        return false;
      }
    }
    else
        repeat = false;
  } while (repeat);

  // allocate bins
  bins.resize(bbin);

  // set cell center and stencils for each bin
  int cId = 0;
  for(typename std::vector<Bin<INTERPOLATE> >::iterator it = bins.begin(); it != bins.end(); ++it)
  {
    const int ibin = it - bins.begin();
    int itmp = ibin;
    const int iz = ibin/(mbinx*mbiny);
    itmp -= iz*mbinx*mbiny;
    const int iy = itmp/mbinx;
    itmp -= iy*mbinx;
    const int ix = itmp;
    it->id = cId++;
    it->center[0] = bsubboxlo[0] + binsizex*((double)(ix+mbinxlo)+0.5);
    it->center[1] = bsubboxlo[1] + binsizey*((double)(iy+mbinylo)+0.5);
    it->center[2] = bsubboxlo[2] + binsizez*((double)(iz+mbinzlo)+0.5);

    setBoundingBox_calc_interpolation_stencil(*it,ibin,ix,iy,iz);

//#ifdef LIGGGHTS_DEBUG
//    printf("Bin (%d) with indizes: %d %d %d\n",ibin,ix,iy,iz);
//    printf("Center of bin (%d): %g %g %g\n",ibin,it->center[0],it->center[1],it->center[2]);
//#endif
  }
  
  // generate stencil which will look at all bins 27 bins
  for (int k = -1; k <= 1; k++)
    for (int j = -1; j <= 1; j++)
      for (int i = -1; i <= 1; i++)
        stencil.push_back(k*mbiny*mbinx + j*mbinx + i);

  bbox_set = true;

  return true;
}

/**
 * @brief Compute the closest distance between central bin (0,0,0) and bin (i,j,k)
 * @param i bin coordinate along x-axis
 * @param j bin coordinate along y-axis
 * @param k bin coordinate along z-axis
 * @return closest distance between central bin (0,0,0) and bin (i,j,k)
 */
template<bool INTERPOLATE>
double RegionNeighborList<INTERPOLATE>::bin_distance(int i, int j, int k)
{
  double delx,dely,delz;

  if (i > 0) delx = (i-1)*binsizex;
  else if (i == 0) delx = 0.0;
  else delx = (i+1)*binsizex;

  if (j > 0) dely = (j-1)*binsizey;
  else if (j == 0) dely = 0.0;
  else dely = (j+1)*binsizey;

  if (k > 0) delz = (k-1)*binsizez;
  else if (k == 0) delz = 0.0;
  else delz = (k+1)*binsizez;

  return (delx*delx + dely*dely + delz*delz);
}

/**
 * @brief Calc local bin index (m) of point x
 * @param x point in 3D
 * @return bin index of the given point x
 */

template<bool INTERPOLATE>
inline void RegionNeighborList<INTERPOLATE>::coord2bin_calc_interpolation_weights(double *x,int ibin,int ix,int iy, int iz,int &quadrant,double &wx,double &wy,double &wz) const
{
    quadrant = 0;
    wx = wy = wz = 0.;
}

template<>
inline void RegionNeighborList<true>::coord2bin_calc_interpolation_weights(double *x,int ibin,int ix,int iy, int iz,int &quadrant,double &wx,double &wy,double &wz) const
{
      double dx = (((x[0]-bboxlo[0])*bininvx) - static_cast<int> ((x[0]-bboxlo[0])*bininvx));//*bininvx;
      double dy = (((x[1]-bboxlo[1])*bininvy) - static_cast<int> ((x[1]-bboxlo[1])*bininvy));//*bininvy;
      double dz = (((x[2]-bboxlo[2])*bininvz) - static_cast<int> ((x[2]-bboxlo[2])*bininvz));//*bininvz;
      quadrant = (dx >= 0.5) * 1 + (dy >= 0.5) * 2 + (dz >= 0.5) * 4;

      if(dx >= 0.5)
        wx = dx-0.5;
      else
        wx = 0.5+dx;

      if(dy >= 0.5)
        wy = dy-0.5;
      else
        wy = 0.5+dy;

      if(dz >= 0.5)
        wz = dz-0.5;
      else
        wz = 0.5+dz;

      int stencil_shift_up = bins[ibin].stencil_shift_up[quadrant];
      int stencil_shift_down = bins[ibin].stencil_shift_down[quadrant];
      if( 0 == stencil_shift_up && 0 == stencil_shift_down)
        return;

      if(stencil_shift_down & 1)
        wx = 1.;
      else if(stencil_shift_up & 1)
        wx = 0.;

      if(stencil_shift_down & 2)
        wy = 1.;
      else if(stencil_shift_up & 2)
        wy = 0.;

      if(stencil_shift_down & 4)
        wz = 1.;
      else if(stencil_shift_up & 4)
        wz = 0.;

}

template<bool INTERPOLATE>
int RegionNeighborList<INTERPOLATE>::coord2bin(double *x,int &quadrant,double &wx,double &wy,double &wz) const
{
  int ix,iy,iz;

  /*if(x[0] < bboxlo[0] || x[0] > bboxhi[0] || x[1] < bboxlo[1] || x[1] > bboxhi[1] || x[2] < bboxlo[2] || x[2] > bboxhi[2])
    return -1;*/

  if (x[0] >= bboxhi[0])
    ix = static_cast<int> ((x[0]-bboxhi[0])*bininvx) + nbinx;
  else if (x[0] >= bboxlo[0]) {
    ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx);
    ix = std::min(ix,nbinx-1);
  } else
    ix = static_cast<int> ((x[0]-bboxlo[0])*bininvx) - 1;

  if (x[1] >= bboxhi[1])
    iy = static_cast<int> ((x[1]-bboxhi[1])*bininvy) + nbiny;
  else if (x[1] >= bboxlo[1]) {
    iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy);
    iy = std::min(iy,nbiny-1);
  } else
    iy = static_cast<int> ((x[1]-bboxlo[1])*bininvy) - 1;

  if (x[2] >= bboxhi[2])
    iz = static_cast<int> ((x[2]-bboxhi[2])*bininvz) + nbinz;
  else if (x[2] >= bboxlo[2]) {
    iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz);
    iz = std::min(iz,nbinz-1);
  } else
    iz = static_cast<int> ((x[2]-bboxlo[2])*bininvz) - 1;

  int ibin = (iz-mbinzlo)*mbiny*mbinx + (iy-mbinylo)*mbinx + (ix-mbinxlo);

  if(ibin < 0 || ibin >= mbins())
     return -1; // ibin = -1
  coord2bin_calc_interpolation_weights(x,ibin,ix,iy,iz,quadrant,wx,wy,wz);

  return ibin;
}

/**
 * @brief Calc global bin index (n) of point x
 * @param x point in 3D
 * @return bin index of the given point x
 */

template<bool INTERPOLATE>
bool RegionNeighborList<INTERPOLATE>::isInBoundingBox(double *pos) const
{
    if(!boundingBoxSet())
        error->one(FLERR,"internal error: call before bbox is set");
    if
    (
        pos[0] >= bboxlo[0] && pos[0] <= bboxhi[0] &&
        pos[1] >= bboxlo[1] && pos[1] <= bboxhi[1] &&
        pos[2] >= bboxlo[2] && pos[2] <= bboxhi[2]
    )   return true;
    return false;
}

/**
 * @brief Set bounding box from region
 * @param region   Region used for creating the neighbor list
 * @param maxrad    largest particle radius
 * @param extend    enable extending the box for ghost particles
 * @param failsafe  limit max. number of bins
 * @return BoundingBox the bounding box of the region
 */

template<bool INTERPOLATE>
BoundingBox RegionNeighborList<INTERPOLATE>::setBoundingBoxRegion(const Region &region, double maxrad, bool extend, bool failsafe)
{
    // use region to determine and set bounding box
    BoundingBox bb(region.extent_xlo, region.extent_xhi, region.extent_ylo, region.extent_yhi, region.extent_zlo, region.extent_zhi);
    if (!setBoundingBox(bb, maxrad, extend, failsafe))
        error->one(FLERR,"internal error: could not set bounding box");

    return bb;
}