Chaste Commit::8b5d759ac2eb95e67ae57699734101efccb0a0a9
ObsoleteBoxCollection.cpp
1/*
2
3Copyright (c) 2005-2024, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, 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
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF 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
44template<unsigned DIM>
45const double ObsoleteBoxCollection<DIM>::msFudge = 5e-14;
46
47template<unsigned DIM>
48ObsoleteBoxCollection<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;
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
94template<unsigned DIM>
96{
97 for (unsigned i = 0; i < mBoxes.size(); i++)
98 {
99 mBoxes[i].ClearNodes();
100 }
101}
102
103template<unsigned DIM>
105{
106 // Get the location of the node
107 c_vector<double, DIM> location = pNode->rGetLocation();
108 return CalculateContainingBox(location);
109}
110
111template<unsigned DIM>
112unsigned 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
137template<unsigned DIM>
139{
140 assert(boxIndex < mBoxes.size());
141 return mBoxes[boxIndex];
142}
144template<unsigned DIM>
146{
147 return mBoxes.size();
148}
150template<unsigned DIM>
151unsigned 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
210template<unsigned DIM>
211c_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
247template<unsigned DIM>
248bool 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
275template<unsigned DIM>
276c_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
288template<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
383template<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
458template<unsigned DIM>
459void 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 {
602 assert(mIsDomainPeriodic(0) && mIsDomainPeriodic(1) && mIsDomainPeriodic(1));
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
620template<unsigned DIM>
621std::set<unsigned>& ObsoleteBoxCollection<DIM>::rGetLocalBoxes(unsigned boxIndex)
622{
623 assert(boxIndex < mLocalBoxes.size());
624 return mLocalBoxes[boxIndex];
625}
626
627template<unsigned DIM>
628const c_vector<double, 2 * DIM>& ObsoleteBoxCollection<DIM>::rGetDomainSize() const
629{
630 return mDomainSize;
631}
632
633template<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
704template class ObsoleteBoxCollection<1>;
705template class ObsoleteBoxCollection<2>;
706template class ObsoleteBoxCollection<3>;
#define EXCEPTION(message)
#define NEVER_REACHED
Definition Box.hpp:51
Definition Node.hpp:59
void AddNeighbour(unsigned index)
Definition Node.cpp:328
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition Node.cpp:139
unsigned GetIndex() const
Definition Node.cpp:158
bool IsBoxInDomain(c_vector< unsigned, DIM > gridIndices)
std::vector< Box< DIM > > mBoxes
void SetupLocalBoxes(const std::vector< c_vector< int, DIM > > &rNeighbours)
c_vector< bool, DIM > mIsDomainPeriodic
Box< DIM > & rGetBox(unsigned boxIndex)
c_vector< unsigned, DIM > GetGridIndices(unsigned linearIndex)
void CalculateNodePairs(const std::vector< Node< DIM > * > &rNodes, std::vector< std::pair< Node< DIM > *, Node< DIM > * > > &rNodePairs)
c_vector< unsigned, DIM > mNumBoxesEachDirection
c_vector< bool, DIM > IsIndexPenultimate(c_vector< unsigned, DIM > gridIndices)
std::set< unsigned > & rGetLocalBoxes(unsigned boxIndex)
unsigned GetLinearIndex(c_vector< int, DIM > gridIndices)
ObsoleteBoxCollection(double boxWidth, c_vector< double, 2 *DIM > domainSize, bool isPeriodicInX=false, bool isPeriodicInY=false, bool isPeriodicInZ=false)
const c_vector< double, 2 *DIM > & rGetDomainSize() const
unsigned CalculateContainingBox(Node< DIM > *pNode)