Chaste  Release::2017.1
ObsoleteBoxCollection.cpp
1 /*
2 
3 Copyright (c) 2005-2017, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions are met:
14  * Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16  * Redistributions in binary form must reproduce the above copyright notice,
17  this list of conditions and the following disclaimer in the documentation
18  and/or other materials provided with the distribution.
19  * Neither the name of the University of Oxford nor the names of its
20  contributors may be used to endorse or promote products derived from this
21  software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 
34 */
35 
36 #include "ObsoleteBoxCollection.hpp"
37 #include "Exception.hpp"
38 
40 // ObsoleteBoxCollection methods
42 
43 // Static member for "fudge factor" is instantiated here
44 template<unsigned DIM>
45 const double ObsoleteBoxCollection<DIM>::msFudge = 5e-14;
46 
47 template<unsigned DIM>
48 ObsoleteBoxCollection<DIM>::ObsoleteBoxCollection(double boxWidth, c_vector<double, 2 * DIM> domainSize, bool isPeriodicInX,
49  bool isPeriodicInY, bool isPeriodicInZ)
50  : mDomainSize(domainSize),
51  mBoxWidth(boxWidth)
52 {
53  // Populate mIsDomainPeriodic
54  switch (DIM)
55  {
56  case 1:
57  {
58  mIsDomainPeriodic[0] = isPeriodicInX;
59  break;
60  }
61  case 2:
62  {
63  mIsDomainPeriodic[0] = isPeriodicInX;
64  mIsDomainPeriodic[1] = isPeriodicInY;
65  break;
66  }
67  case 3:
68  {
69  mIsDomainPeriodic[0] = isPeriodicInX;
70  mIsDomainPeriodic[1] = isPeriodicInY;
71  mIsDomainPeriodic[2] = isPeriodicInZ;
72  break;
73  }
74  default:
75  {
77  }
78  }
79 
80  // Calculating the number of boxes in each direction and total number of boxes.
81  unsigned num_boxes = 1;
82 
83  for (unsigned i = 0; i < DIM; i++)
84  {
86  mNumBoxesEachDirection(i) = (unsigned) floor((domainSize(2 * i + 1) - domainSize(2 * i)) / boxWidth + msFudge) + 1;
87  num_boxes *= mNumBoxesEachDirection(i);
88  }
89 
90  // Create the correct number of boxes
91  mBoxes.resize(num_boxes);
92 }
93 
94 template<unsigned DIM>
96 {
97  for (unsigned i = 0; i < mBoxes.size(); i++)
98  {
99  mBoxes[i].ClearNodes();
100  }
101 }
102 
103 template<unsigned DIM>
105 {
106  // Get the location of the node
107  c_vector<double, DIM> location = pNode->rGetLocation();
108  return CalculateContainingBox(location);
109 }
110 
111 template<unsigned DIM>
112 unsigned ObsoleteBoxCollection<DIM>::CalculateContainingBox(c_vector<double, DIM>& rLocation)
113 {
114  // Confirm that the location is in the domain
115  for (unsigned i = 0; i < DIM; i++)
116  {
117  if (!(rLocation[i] >= mDomainSize[2*i] && rLocation[i] <= mDomainSize[2*i + 1]))
118  {
119  std::stringstream location_error;
120  location_error << "Location in dimension " << i << " is " << rLocation[i] << " which is not in the domain ["
121  << mDomainSize[2*i] << ", " << mDomainSize[2*i + 1] << "].";
122 
123  EXCEPTION(location_error.str());
124  }
125  }
126 
127  // Compute the containing box index in each dimension
128  c_vector<int, DIM> containing_box_indices;
129  for (unsigned i = 0; i < DIM; i++)
130  {
131  containing_box_indices[i] = (int) floor((rLocation[i] - mDomainSize(2 * i) + msFudge) / mBoxWidth);
132  }
133 
134  return GetLinearIndex(containing_box_indices);
135 }
136 
137 template<unsigned DIM>
139 {
140  assert(boxIndex < mBoxes.size());
141  return mBoxes[boxIndex];
142 }
143 
144 template<unsigned DIM>
146 {
147  return mBoxes.size();
148 }
149 
150 template<unsigned DIM>
151 unsigned ObsoleteBoxCollection<DIM>::GetLinearIndex(c_vector<int, DIM> gridIndices)
152 {
153  /*
154  * This function may be passed values outside the range in one or more
155  * dimensions in the case of a periodic domain. We therefore assume that
156  * these values represent a situation with periodicity and adjust them
157  * accordingly before calculating the linear index.
158  */
159 
160  // Adjust for periodicity if necessary
161  for (unsigned dim = 0; dim < DIM; dim++)
162  {
163  // Check for values too large
164  if (gridIndices(dim) >= (int)mNumBoxesEachDirection(dim))
165  {
166  assert(mIsDomainPeriodic(dim));
167  gridIndices(dim) -= (int)mNumBoxesEachDirection(dim);
168  }
169 
170  // Check for negative values
171  else if (gridIndices(dim) < 0)
172  {
173  assert(mIsDomainPeriodic(dim));
174  gridIndices(dim) += (int)mNumBoxesEachDirection(dim);
175  }
176  }
177 
178  // Calculate linear index
179  unsigned linear_index;
180 
181  switch (DIM)
182  {
183  case 1:
184  {
185  linear_index = gridIndices(0);
186  break;
187  }
188  case 2:
189  {
190  linear_index = gridIndices(0) +
191  gridIndices(1) * mNumBoxesEachDirection(0);
192  break;
193  }
194  case 3:
195  {
196  linear_index = gridIndices(0) +
197  gridIndices(1) * mNumBoxesEachDirection(0) +
198  gridIndices(2) * mNumBoxesEachDirection(0) * mNumBoxesEachDirection(1);
199  break;
200  }
201  default:
202  {
204  }
205  }
206 
207  return linear_index;
208 }
209 
210 template<unsigned DIM>
211 c_vector<unsigned, DIM> ObsoleteBoxCollection<DIM>::GetGridIndices(unsigned linearIndex)
212 {
213  c_vector<unsigned, DIM> grid_indices;
214 
215  switch (DIM)
216  {
217  case 1:
218  {
219  grid_indices(0) = linearIndex;
220  break;
221  }
222  case 2:
223  {
224  unsigned num_x = mNumBoxesEachDirection(0);
225  grid_indices(0) = linearIndex % num_x;
226  grid_indices(1) = (linearIndex - grid_indices(0)) / num_x;
227  break;
228  }
229  case 3:
230  {
231  unsigned num_x = mNumBoxesEachDirection(0);
232  unsigned num_xy = mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1);
233  grid_indices(0) = linearIndex % num_x;
234  grid_indices(1) = (linearIndex % num_xy - grid_indices(0)) / num_x;
235  grid_indices(2) = linearIndex / num_xy;
236  break;
237  }
238  default:
239  {
241  }
242  }
243 
244  return grid_indices;
245 }
246 
247 template<unsigned DIM>
248 bool ObsoleteBoxCollection<DIM>::IsBoxInDomain(c_vector<unsigned, DIM> gridIndices)
249 {
250  /*
251  * We assume that, for a given dimension, any location is in the domain
252  * if the domain is periodic in that dimension.
253  *
254  * This method can only return false in the case of one or more
255  * dimensions being aperiodic and a location in one of those dimensions
256  * being outside the range.
257  */
258 
259  bool is_in_domain = true;
260 
261  for (unsigned dim = 0; dim < DIM; dim++)
262  {
263  if (!mIsDomainPeriodic(dim))
264  {
265  if (gridIndices(dim) >= mNumBoxesEachDirection(dim))
266  {
267  is_in_domain = false;
268  }
269  }
270  }
271 
272  return is_in_domain;
273 }
274 
275 template<unsigned DIM>
276 c_vector<bool,DIM> ObsoleteBoxCollection<DIM>::IsIndexPenultimate(c_vector<unsigned, DIM> gridIndices)
277 {
278  c_vector<bool,DIM> is_penultimate;
279 
280  for (unsigned dim = 0 ; dim < DIM ; dim++)
281  {
282  is_penultimate(dim) = (gridIndices(dim) == mNumBoxesEachDirection(dim) - 2);
283  }
284 
285  return is_penultimate;
286 }
287 
288 template<unsigned DIM>
290 {
291  // Populate a list of half the neighbours in this number of dimensions
292  std::vector<c_vector<int,DIM> > neighbours;
293 
294  switch (DIM)
295  {
296  case 1:
297  {
298  // Just one neighbour, plus the current box (zero vector)
299  neighbours = std::vector<c_vector<int,DIM> >(2);
300 
301  neighbours[0](0) = 0; // current box
302  neighbours[1](0) = 1; // right
303 
304  break;
305  }
306  case 2:
307  {
308  // Four neighbours, plus the current box (zero vector)
309  neighbours = std::vector<c_vector<int,DIM> >(5);
310 
311  neighbours[0](0) = 0; neighbours[0](1) = 1; // up
312  neighbours[1](0) = 1; neighbours[1](1) = 1; // up right
313  neighbours[2](0) = 1; neighbours[2](1) = 0; // right
314  neighbours[3](0) = 1; neighbours[3](1) =-1; // down right
315  neighbours[4](0) = 0; neighbours[4](1) = 0; // current box
316 
317  break;
318  }
319  case 3:
320  {
321  /*
322  * We need to pick 13 neighbours in such a way as to ensure all interactions are captured,
323  * in addition to the current box.
324  *
325  * The 26 cubes on the outside of a 3x3 arrangement either adjacent to a whole face of
326  * the central cube, only an edge of the central cube, or only a vertex of the central
327  * cube:
328  *
329  * 6 contact faces, and come in the following 3 pairs:
330  * +x -x (1, 0, 0)
331  * +y -y (0, 1, 0)
332  * +z -z (0, 0, 1)
333  *
334  * 12 contact edges, and come in the following 6 pairs:
335  * +x+y -x-y (1, 1, 0)
336  * +x+z -x-z (1, 0, 1)
337  * +x-y -x+y (1,-1, 0)
338  * +x-z -x+z (1, 0,-1)
339  * +y+z -y-z (0, 1, 1)
340  * +y-z -y+z (0, 1,-1)
341  *
342  * 8 contact vertices, and come in the following 4 pairs:
343  * +x+y+z -x-y-z (1, 1, 1)
344  * +x+y-z -x-y+z (1, 1,-1)
345  * +x-y+z -x+y-z (1,-1, 1)
346  * +x-y-z -x+y+z (1,-1,-1)
347  *
348  * We will simply pick the 13 from the left-hand column above, which can be represented
349  * as an integer offset in three dimensions from the middle cube, as shown in the third
350  * column above.
351  */
352 
353  neighbours = std::vector<c_vector<int,DIM> >(14);
354 
355  neighbours[0](0) = 1; neighbours[0](1) = 0; neighbours[0](2) = 0;
356  neighbours[1](0) = 0; neighbours[1](1) = 1; neighbours[1](2) = 0;
357  neighbours[2](0) = 0; neighbours[2](1) = 0; neighbours[2](2) = 1;
358  neighbours[3](0) = 1; neighbours[3](1) = 1; neighbours[3](2) = 0;
359  neighbours[4](0) = 1; neighbours[4](1) = 0; neighbours[4](2) = 1;
360  neighbours[5](0) = 1; neighbours[5](1) =-1; neighbours[5](2) = 0;
361  neighbours[6](0) = 1; neighbours[6](1) = 0; neighbours[6](2) =-1;
362  neighbours[7](0) = 0; neighbours[7](1) = 1; neighbours[7](2) = 1;
363  neighbours[8](0) = 0; neighbours[8](1) = 1; neighbours[8](2) =-1;
364  neighbours[9](0) = 1; neighbours[9](1) = 1; neighbours[9](2) = 1;
365  neighbours[10](0) = 1; neighbours[10](1) = 1; neighbours[10](2) =-1;
366  neighbours[11](0) = 1; neighbours[11](1) =-1; neighbours[11](2) = 1;
367  neighbours[12](0) = 1; neighbours[12](1) =-1; neighbours[12](2) =-1;
368 
369  neighbours[13](0) = 0; neighbours[13](1) = 0; neighbours[13](2) = 0; // current box
370 
371  break;
372  }
373  default:
374  {
376  }
377  }
378 
379  // Pass the list of possible neighbours to SetupLocalBoxes()
380  SetupLocalBoxes(neighbours);
381 }
382 
383 template<unsigned DIM>
385 {
386  // Populate a list of all neighbours in this number of dimensions
387  std::vector<c_vector<int, DIM> > neighbours;
388 
389  switch (DIM)
390  {
391  case 1:
392  {
393  // 3 neighbours
394  neighbours.clear();
395 
396  for (int x_dim = -1 ; x_dim < 2 ; x_dim++)
397  {
398  c_vector<int, DIM> neighbour;
399  neighbour(0) = x_dim;
400 
401  neighbours.push_back(neighbour);
402  }
403 
404  break;
405  }
406  case 2:
407  {
408  // 3x3 neighbours
409  neighbours.clear();
410 
411  for (int x_dim = -1 ; x_dim < 2 ; x_dim++)
412  {
413  for (int y_dim = -1 ; y_dim < 2 ; y_dim++)
414  {
415  c_vector<int, DIM> neighbour;
416  neighbour(0) = x_dim;
417  neighbour(1) = y_dim;
418 
419  neighbours.push_back(neighbour);
420  }
421  }
422 
423  break;
424  }
425  case 3:
426  {
427  // 3x3x3 neighbours
428  neighbours.clear();
429 
430  for (int x_dim = -1 ; x_dim < 2 ; x_dim++)
431  {
432  for (int y_dim = -1 ; y_dim < 2 ; y_dim++)
433  {
434  for (int z_dim = -1 ; z_dim < 2 ; z_dim++)
435  {
436  c_vector<int, DIM> neighbour;
437  neighbour(0) = x_dim;
438  neighbour(1) = y_dim;
439  neighbour(2) = z_dim;
440 
441  neighbours.push_back(neighbour);
442  }
443  }
444  }
445 
446  break;
447  }
448  default:
449  {
451  }
452  }
453 
454  // Pass the list of possible neighbours to SetupLocalBoxes()
455  SetupLocalBoxes(neighbours);
456 }
457 
458 template<unsigned DIM>
459 void ObsoleteBoxCollection<DIM>::SetupLocalBoxes(const std::vector<c_vector<int, DIM> >& rNeighbours)
460 {
461  mLocalBoxes.clear();
462 
463  // Loop over all boxes and add all necessary local boxes
464  for (unsigned box_idx = 0 ; box_idx < mBoxes.size() ; box_idx++)
465  {
466  std::set<unsigned> local_boxes;
467 
468  // The grid indices (i), (i,j) or (i,j,k) depending on DIM, corresponding to box_idx
469  c_vector<unsigned, DIM> grid_indices = GetGridIndices(box_idx);
470 
471  // Check all neighbours (1 or 2 in 1D, 4 or 8 in 2D, 13 or 26 in 3D) and add them as local
472  // boxes if they are in the domain
473  for (unsigned neighbour = 0 ; neighbour < rNeighbours.size() ; neighbour++)
474  {
475  if (IsBoxInDomain(grid_indices + rNeighbours[neighbour]))
476  {
477  local_boxes.insert(GetLinearIndex(grid_indices + rNeighbours[neighbour]));
478  }
479  }
480 
481  /*
482  * If we are in a periodic domain, we need to add additional boxes if the
483  * current box is in the penultimate position of any dimension.
484  *
485  * The additional boxes we need to add are just all the neighbours of the box
486  * in the final position in that dimension. Because we use set::insert, it
487  * doesn't matter if we try and add the same box multiple times (only one
488  * copy of the index will be included).
489  */
490 
491  // Find if the current indices are penultimate in any dimension in which collection is periodic
492  c_vector<bool, DIM> is_penultimate_periodic = IsIndexPenultimate(grid_indices);
493  unsigned num_penultimate_periodic_dimensions = 0;
494 
495  for (unsigned dim = 0 ; dim < DIM ; dim++)
496  {
497  is_penultimate_periodic(dim) = is_penultimate_periodic(dim) && mIsDomainPeriodic(dim);
498  if (is_penultimate_periodic(dim))
499  {
500  num_penultimate_periodic_dimensions++;
501  }
502  }
503 
504  // First, deal with at least one penultimate dimension
505  if (num_penultimate_periodic_dimensions > 0)
506  {
507  // Loop over each dimension. If penultimate in dimension DIM move one box and add all neighbours
508  for (unsigned dim = 0 ; dim < DIM ; dim++)
509  {
510  if (is_penultimate_periodic(dim))
511  {
512  // If we're penultimate in dimension dim, move to the final location and add each neighbour as before.
513  // The call to IsBoxInDomain() will handle periodicity.
514  // Note that we define this vector before setting it as otherwise the profiling build will break (see #2367)
515  c_vector<unsigned, DIM> ultimate_indices; // Initialisation on next line for profile compiler
516  ultimate_indices = grid_indices;
517  ultimate_indices(dim) ++;
518 
519  for (unsigned neighbour = 0 ; neighbour < rNeighbours.size() ; neighbour++)
520  {
521  if (IsBoxInDomain(ultimate_indices + rNeighbours[neighbour]))
522  {
523  local_boxes.insert(GetLinearIndex(ultimate_indices + rNeighbours[neighbour]));
524  }
525  }
526  }
527  }
528  }
529 
530  // The final consideration is cases of multiple dimensions of periodicity.
531  if (num_penultimate_periodic_dimensions > 1)
532  {
533  switch (DIM)
534  {
535  case 2:
536  {
537  // Must have x and y periodicity - just have to add one extra box
538  assert(mIsDomainPeriodic(0) && mIsDomainPeriodic(1));
539 
540  local_boxes.insert(0);
541 
542  break;
543  }
544  case 3:
545  {
546  // Could have X and Y, X and Z, Y and Z, or X, Y and Z periodicity
547 
548  // X and Y
549  if (is_penultimate_periodic(0) && is_penultimate_periodic(1))
550  {
551  c_vector<unsigned, DIM> ultimate_indices;
552  ultimate_indices = grid_indices;
553  ultimate_indices(0) ++;
554  ultimate_indices(1) ++;
555 
556  for (unsigned neighbour = 0 ; neighbour < rNeighbours.size() ; neighbour++)
557  {
558  if (IsBoxInDomain(ultimate_indices + rNeighbours[neighbour]))
559  {
560  local_boxes.insert(GetLinearIndex(ultimate_indices + rNeighbours[neighbour]));
561  }
562  }
563  }
564 
565  // X and Z
566  if (is_penultimate_periodic(0) && is_penultimate_periodic(2))
567  {
568  c_vector<unsigned, DIM> ultimate_indices;
569  ultimate_indices = grid_indices;
570  ultimate_indices(0) ++;
571  ultimate_indices(2) ++;
572 
573  for (unsigned neighbour = 0 ; neighbour < rNeighbours.size() ; neighbour++)
574  {
575  if (IsBoxInDomain(ultimate_indices + rNeighbours[neighbour]))
576  {
577  local_boxes.insert(GetLinearIndex(ultimate_indices + rNeighbours[neighbour]));
578  }
579  }
580  }
581 
582  // Y and Z
583  if (is_penultimate_periodic(1) && is_penultimate_periodic(2))
584  {
585  c_vector<unsigned, DIM> ultimate_indices;
586  ultimate_indices = grid_indices;
587  ultimate_indices(1) ++;
588  ultimate_indices(2) ++;
589 
590  for (unsigned neighbour = 0 ; neighbour < rNeighbours.size() ; neighbour++)
591  {
592  if (IsBoxInDomain(ultimate_indices + rNeighbours[neighbour]))
593  {
594  local_boxes.insert(GetLinearIndex(ultimate_indices + rNeighbours[neighbour]));
595  }
596  }
597  }
598 
599  // X Y and Z
600  if (num_penultimate_periodic_dimensions == 3)
601  {
603  local_boxes.insert(0);
604  }
605 
606  break;
607  }
608  default:
609  {
611  }
612  }
613  }
614 
615  // Add the local boxes to the member vector
616  mLocalBoxes.push_back(local_boxes);
617  }
618 }
619 
620 template<unsigned DIM>
621 std::set<unsigned>& ObsoleteBoxCollection<DIM>::rGetLocalBoxes(unsigned boxIndex)
622 {
623  assert(boxIndex < mLocalBoxes.size());
624  return mLocalBoxes[boxIndex];
625 }
626 
627 template<unsigned DIM>
628 const c_vector<double, 2 * DIM>& ObsoleteBoxCollection<DIM>::rGetDomainSize() const
629 {
630  return mDomainSize;
631 }
632 
633 template<unsigned DIM>
635  std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs)
636 {
637  rNodePairs.clear();
638 
639  // Ensure all boxes are empty
640  EmptyBoxes();
641 
642  // Create an empty set of neighbours for each node, and add each node to its correct box
643  for (unsigned node_index = 0; node_index < rNodes.size(); node_index++)
644  {
645  rNodes[node_index]->ClearNeighbours();
646 
647  unsigned box_index = CalculateContainingBox(rNodes[node_index]);
648  mBoxes[box_index].AddNode(rNodes[node_index]);
649  }
650 
651  for (unsigned i = 0; i < rNodes.size(); i++)
652  {
653  Node<DIM>* this_node = rNodes[i];
654  unsigned node_index = this_node->GetIndex();
655 
656  // Get the box containing this node
657  unsigned this_node_box_index = CalculateContainingBox(this_node);
658 
659  // Get the local boxes to this node
660  std::set<unsigned> local_boxes_indices = rGetLocalBoxes(this_node_box_index);
661 
662  // Loop over all the local boxes
663  for (std::set<unsigned>::iterator box_iter = local_boxes_indices.begin(); box_iter != local_boxes_indices.end();
664  box_iter++)
665  {
666  // Get the set of nodes contained in this box
667  std::set<Node<DIM>*>& r_contained_nodes = mBoxes[*box_iter].rGetNodesContained();
668 
669  // Loop over these nodes
670  for (typename std::set<Node<DIM>*>::iterator node_iter = r_contained_nodes.begin();
671  node_iter != r_contained_nodes.end(); ++node_iter)
672  {
673  // Get the index of the other node
674  unsigned other_node_index = (*node_iter)->GetIndex();
675 
676  // If we're in the same box, then take care not to store the node pair twice
677  if (*box_iter == this_node_box_index)
678  {
679  if (other_node_index > this_node->GetIndex())
680  {
681  rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>(this_node, (*node_iter)));
682  this_node->AddNeighbour(other_node_index);
683  (*node_iter)->AddNeighbour(node_index);
684  }
685  }
686  else
687  {
688  rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>(this_node, (*node_iter)));
689  this_node->AddNeighbour(other_node_index);
690  (*node_iter)->AddNeighbour(node_index);
691  }
692  }
693  }
694  }
695 
696  for (unsigned i = 0; i < rNodes.size(); i++)
697  {
698  rNodes[i]->RemoveDuplicateNeighbours();
699  }
700 }
701 
703 
704 template class ObsoleteBoxCollection<1>;
705 template class ObsoleteBoxCollection<2>;
706 template class ObsoleteBoxCollection<3>;
Definition: Node.hpp:58
std::set< unsigned > & rGetLocalBoxes(unsigned boxIndex)
c_vector< double, 2 *DIM > mDomainSize
#define EXCEPTION(message)
Definition: Exception.hpp:143
std::vector< Box< DIM > > mBoxes
static const double msFudge
c_vector< bool, DIM > mIsDomainPeriodic
#define NEVER_REACHED
Definition: Exception.hpp:206
ObsoleteBoxCollection(double boxWidth, c_vector< double, 2 *DIM > domainSize, bool isPeriodicInX=false, bool isPeriodicInY=false, bool isPeriodicInZ=false)
bool IsBoxInDomain(c_vector< unsigned, DIM > gridIndices)
unsigned CalculateContainingBox(Node< DIM > *pNode)
c_vector< bool, DIM > IsIndexPenultimate(c_vector< unsigned, DIM > gridIndices)
std::vector< std::set< unsigned > > mLocalBoxes
void AddNeighbour(unsigned index)
Definition: Node.cpp:328
Definition: Box.hpp:50
void CalculateNodePairs(std::vector< Node< DIM > * > &rNodes, std::vector< std::pair< Node< DIM > *, Node< DIM > * > > &rNodePairs)
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition: Node.cpp:139
c_vector< unsigned, DIM > GetGridIndices(unsigned linearIndex)
Box< DIM > & rGetBox(unsigned boxIndex)
unsigned GetLinearIndex(c_vector< int, DIM > gridIndices)
const c_vector< double, 2 *DIM > & rGetDomainSize() const
unsigned GetIndex() const
Definition: Node.cpp:158
void SetupLocalBoxes(const std::vector< c_vector< int, DIM > > &rNeighbours)
c_vector< unsigned, DIM > mNumBoxesEachDirection