Chaste Release::3.1
|
00001 /* 00002 00003 Copyright (c) 2005-2012, University of Oxford. 00004 All rights reserved. 00005 00006 University of Oxford means the Chancellor, Masters and Scholars of the 00007 University of Oxford, having an administrative office at Wellington 00008 Square, Oxford OX1 2JD, UK. 00009 00010 This file is part of Chaste. 00011 00012 Redistribution and use in source and binary forms, with or without 00013 modification, are permitted provided that the following conditions are met: 00014 * Redistributions of source code must retain the above copyright notice, 00015 this list of conditions and the following disclaimer. 00016 * Redistributions in binary form must reproduce the above copyright notice, 00017 this list of conditions and the following disclaimer in the documentation 00018 and/or other materials provided with the distribution. 00019 * Neither the name of the University of Oxford nor the names of its 00020 contributors may be used to endorse or promote products derived from this 00021 software without specific prior written permission. 00022 00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00033 00034 */ 00035 #include "BoxCollection.hpp" 00036 #include "Exception.hpp" 00037 00039 // Box methods 00041 00042 00043 template<unsigned DIM> 00044 Box<DIM>::Box(c_vector<double, 2*DIM>& rMinAndMaxValues) 00045 { 00046 mMinAndMaxValues = rMinAndMaxValues; 00047 } 00048 00049 template<unsigned DIM> 00050 c_vector<double, 2*DIM>& Box<DIM>::rGetMinAndMaxValues() 00051 { 00052 return mMinAndMaxValues; 00053 } 00054 00055 template<unsigned DIM> 00056 void Box<DIM>::AddNode(Node<DIM>* pNode) 00057 { 00058 mNodesContained.insert(pNode); 00059 } 00060 00061 template<unsigned DIM> 00062 void Box<DIM>::RemoveNode(Node<DIM>* pNode) 00063 { 00064 mNodesContained.erase(pNode); 00065 } 00066 00067 template<unsigned DIM> 00068 std::set< Node<DIM>* >& Box<DIM>::rGetNodesContained() 00069 { 00070 return mNodesContained; 00071 } 00072 00073 template<unsigned DIM> 00074 void Box<DIM>::AddElement(Element<DIM,DIM>* pElement) 00075 { 00076 mElementsContained.insert(pElement); 00077 } 00078 00079 template<unsigned DIM> 00080 std::set< Element<DIM,DIM>* >& Box<DIM>::rGetElementsContained() 00081 { 00082 return mElementsContained; 00083 } 00084 00085 00087 // BoxCollection methods 00089 00090 00091 template<unsigned DIM> 00092 BoxCollection<DIM>::BoxCollection(double boxWidth, c_vector<double, 2*DIM> domainSize) 00093 : mDomainSize(domainSize), 00094 mBoxWidth(boxWidth) 00095 { 00096 /* 00097 * Start by calculating the number of boxes in each direction and total number of boxes. 00098 * Also create a helper vector of coefficients, whose first entry is 1 and whose i-th 00099 * entry (for i>1) is the i-th partial product of the vector mNumBoxesEachDirection. This 00100 * vector of coefficients will be used in the next code block to compute how many boxes 00101 * along in each dimension each box, given its index. 00102 */ 00103 unsigned num_boxes = 1; 00104 std::vector<unsigned> coefficients; 00105 coefficients.push_back(1); 00106 00107 for (unsigned i=0; i<DIM; i++) 00108 { 00109 mNumBoxesEachDirection(i) = floor((domainSize(2*i+1) - domainSize(2*i))/boxWidth + mFudge) + 1; 00110 num_boxes *= mNumBoxesEachDirection(i); 00111 coefficients.push_back(coefficients[i]*mNumBoxesEachDirection(i)); 00112 } 00113 00114 for (unsigned box_index=0; box_index<num_boxes; box_index++) 00115 { 00116 /* 00117 * The code block below computes how many boxes along in each dimension the 00118 * current box is and stores this information in the second, ..., (DIM+1)th 00119 * entries of the vector current_box_indices. The first entry of 00120 * current_box_indices is zero to ensure that the for loop works correctly. 00121 * 00122 * Our convention is that in 3D the index of each box, box_index, is related 00123 * to its indices (i,j,k) by 00124 * 00125 * box_index = i + mNumBoxesEachDirection(0)*j 00126 * + mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1)*k, 00127 * 00128 * while in 2D, box_index is related to (i,j) by 00129 * 00130 * box_index = i + mNumBoxesEachDirection(0)*j 00131 * 00132 * and in 1D we simply have box_index = i. 00133 */ 00134 c_vector<unsigned, DIM+1> current_box_indices; 00135 current_box_indices[0] = 0; 00136 00137 for (unsigned i=0; i<DIM; i++) 00138 { 00139 unsigned temp = 0; 00140 for (unsigned j=1; j<i; j++) 00141 { 00142 temp += coefficients[j]*current_box_indices[j-1]; 00143 } 00144 current_box_indices[i+1] = (box_index%coefficients[i+1] - temp)/coefficients[i]; 00145 } 00146 00147 /* 00148 * We now use the information stores in current_box_indices to construct the 00149 * Box, which we add to mBoxes. 00150 */ 00151 c_vector<double, 2*DIM> box_coords; 00152 for (unsigned l=0; l<DIM; l++) 00153 { 00154 box_coords(2*l) = domainSize(2*l) + current_box_indices(l+1)*boxWidth; 00155 box_coords(2*l+1) = domainSize(2*l) + (current_box_indices(l+1)+1)*boxWidth; 00156 } 00157 00158 Box<DIM> new_box(box_coords); 00159 mBoxes.push_back(new_box); 00160 } 00161 00162 // Check that we have the correct number of boxes 00163 assert(num_boxes == mBoxes.size()); 00164 } 00165 00166 template<unsigned DIM> 00167 unsigned BoxCollection<DIM>::CalculateContainingBox(Node<DIM>* pNode) 00168 { 00169 // Get the location of the node 00170 c_vector<double, DIM> location = pNode->rGetLocation(); 00171 return CalculateContainingBox(location); 00172 } 00173 00174 00175 template<unsigned DIM> 00176 unsigned BoxCollection<DIM>::CalculateContainingBox(c_vector<double, DIM>& rLocation) 00177 { 00178 // The node must lie inside the boundary of the box collection 00179 for (unsigned i=0; i<DIM; i++) 00180 { 00181 if ( (rLocation[i] < mDomainSize(2*i)) || (rLocation[i] > mDomainSize(2*i+1)) ) 00182 { 00183 EXCEPTION("The point provided is outside all of the boxes"); 00184 } 00185 } 00186 00187 // Compute the containing box index in each dimension 00188 c_vector<unsigned, DIM> containing_box_indices; 00189 for (unsigned i=0; i<DIM; i++) 00190 { 00191 containing_box_indices[i] = (unsigned) floor((rLocation[i] - mDomainSize(2*i) + mFudge)/mBoxWidth); 00192 } 00193 00194 // Use these to compute the index of the containing box 00195 unsigned containing_box_index = 0; 00196 for (unsigned i=0; i<DIM; i++) 00197 { 00198 unsigned temp = 1; 00199 for (unsigned j=0; j<i; j++) 00200 { 00201 temp *= mNumBoxesEachDirection(j); 00202 } 00203 containing_box_index += temp*containing_box_indices[i]; 00204 } 00205 00206 // This index must be less than the number of boxes 00207 assert(containing_box_index < mBoxes.size()); 00208 00209 return containing_box_index; 00210 } 00211 00212 template<unsigned DIM> 00213 Box<DIM>& BoxCollection<DIM>::rGetBox(unsigned boxIndex) 00214 { 00215 assert(boxIndex < mBoxes.size()); 00216 return mBoxes[boxIndex]; 00217 } 00218 00219 template<unsigned DIM> 00220 unsigned BoxCollection<DIM>::GetNumBoxes() 00221 { 00222 return mBoxes.size(); 00223 } 00224 00225 template<unsigned DIM> 00226 void BoxCollection<DIM>::SetupLocalBoxesHalfOnly() 00227 { 00228 switch (DIM) 00229 { 00230 case 1: 00231 { 00232 // We only need to look for neighbours in the current and successive boxes 00233 mLocalBoxes.clear(); 00234 for (unsigned box_index=0; box_index<mBoxes.size(); box_index++) 00235 { 00236 std::set<unsigned> local_boxes; 00237 00238 // Insert the current box 00239 local_boxes.insert(box_index); 00240 00241 // If we're not at the right-most box, then insert the box to the right 00242 if (box_index < mNumBoxesEachDirection(0)-1) 00243 { 00244 local_boxes.insert(box_index+1); 00245 } 00246 mLocalBoxes.push_back(local_boxes); 00247 } 00248 break; 00249 } 00250 case 2: 00251 { 00252 // We only need to look for neighbours in the current box and half the neighbouring boxes 00253 mLocalBoxes.clear(); 00254 for (unsigned box_index=0; box_index<mBoxes.size(); box_index++) 00255 { 00256 std::set<unsigned> local_boxes; 00257 00258 // Insert the current box 00259 local_boxes.insert(box_index); 00260 00261 // If we're not on the top-most row, then insert the box above 00262 if (box_index < mBoxes.size() - mNumBoxesEachDirection(0)) 00263 { 00264 local_boxes.insert(box_index + mNumBoxesEachDirection(0)); 00265 00266 // If we're also not on the left-most column, then insert the box above-left 00267 if (box_index % mNumBoxesEachDirection(0) != 0) 00268 { 00269 local_boxes.insert(box_index + mNumBoxesEachDirection(0) - 1); 00270 } 00271 } 00272 // If we're not on the right-most column, then insert the box to the right 00273 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1) 00274 { 00275 local_boxes.insert(box_index + 1); 00276 00277 // If we're also not on the top-most row, then insert the box above-right 00278 if (box_index < mBoxes.size() - mNumBoxesEachDirection(0)) 00279 { 00280 local_boxes.insert(box_index + mNumBoxesEachDirection(0) + 1); 00281 } 00282 } 00283 00284 mLocalBoxes.push_back(local_boxes); 00285 } 00286 break; 00287 } 00288 case 3: 00289 { 00290 // We only need to look for neighbours in the current box and half the neighbouring boxes 00291 mLocalBoxes.clear(); 00292 unsigned num_boxes_xy = mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1); 00293 00294 for (unsigned box_index=0; box_index<mBoxes.size(); box_index++) 00295 { 00296 std::set<unsigned> local_boxes; 00297 00298 // Insert the current box 00299 local_boxes.insert(box_index); 00300 00301 // If we're not on the far face (y max), then insert the far box 00302 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0)) 00303 { 00304 local_boxes.insert(box_index + mNumBoxesEachDirection(0)); 00305 00306 // If we're also not on the left face (x min), then insert the box to the left 00307 if (box_index % mNumBoxesEachDirection(0) != 0) 00308 { 00309 local_boxes.insert(box_index + mNumBoxesEachDirection(0) - 1); 00310 } 00311 } 00312 // If we're not on the right face (x max), then insert the box to the right 00313 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1) 00314 { 00315 local_boxes.insert(box_index + 1); 00316 00317 // If we're also not on the far face (y max) row, then insert the box to the far-right 00318 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0)) 00319 { 00320 local_boxes.insert(box_index + mNumBoxesEachDirection(0) + 1); 00321 } 00322 } 00323 // If we're not on the top face (z max), then insert the box above 00324 if (box_index < mBoxes.size() - num_boxes_xy) 00325 { 00326 local_boxes.insert(box_index + num_boxes_xy); 00327 00328 // If we're also not on the far face (y max), then insert the above-far box 00329 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0)) 00330 { 00331 local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0)); 00332 00333 // If we're also not on the left face (x min), then insert the box to the above-left 00334 if (box_index % mNumBoxesEachDirection(0) != 0) 00335 { 00336 local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0) - 1); 00337 } 00338 } 00339 // If we're also not on the right face (x max), then insert the box to the above-right 00340 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1) 00341 { 00342 local_boxes.insert(box_index + num_boxes_xy + 1); 00343 00344 // If we're also not on the far face (y max) row, then insert the box to the above-far-right 00345 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0)) 00346 { 00347 local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0) + 1); 00348 } 00349 } 00350 } 00351 // If we're not on the bottom face (z min), then insert the box above 00352 if (box_index >= num_boxes_xy) 00353 { 00354 local_boxes.insert(box_index - num_boxes_xy); 00355 00356 // If we're also not on the far face (y max), then insert the below-far box 00357 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0)) 00358 { 00359 local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0)); 00360 00361 // If we're also not on the left face (x min), then insert the box to the below-left 00362 if (box_index % mNumBoxesEachDirection(0) != 0) 00363 { 00364 local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0) - 1); 00365 } 00366 } 00367 // If we're also not on the right face (x max), then insert the box to the below-right 00368 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1) 00369 { 00370 local_boxes.insert(box_index - num_boxes_xy + 1); 00371 00372 // If we're also not on the far face (y max) row, then insert the box to the below-far-right 00373 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0)) 00374 { 00375 local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0) + 1); 00376 } 00377 } 00378 } 00379 mLocalBoxes.push_back(local_boxes); 00380 } 00381 break; 00382 } 00383 default: 00384 NEVER_REACHED; 00385 } 00386 } 00387 00388 00389 00390 template<unsigned DIM> 00391 void BoxCollection<DIM>::SetupAllLocalBoxes() 00392 { 00393 switch (DIM) 00394 { 00395 case 1: 00396 { 00397 for (unsigned i=0; i<mBoxes.size(); i++) 00398 { 00399 std::set<unsigned> local_boxes; 00400 00401 local_boxes.insert(i); 00402 00403 // add the two neighbours 00404 if (i!=0) 00405 { 00406 local_boxes.insert(i-1); 00407 } 00408 if (i+1 != mNumBoxesEachDirection(0)) 00409 { 00410 local_boxes.insert(i+1); 00411 } 00412 00413 mLocalBoxes.push_back(local_boxes); 00414 } 00415 break; 00416 } 00417 case 2: 00418 { 00419 mLocalBoxes.clear(); 00420 00421 unsigned M = mNumBoxesEachDirection(0); 00422 unsigned N = mNumBoxesEachDirection(1); 00423 00424 std::vector<bool> is_xmin(N*M); // far left 00425 std::vector<bool> is_xmax(N*M); // far right 00426 std::vector<bool> is_ymin(N*M); // bottom 00427 std::vector<bool> is_ymax(N*M); // top 00428 00429 for (unsigned i=0; i<M*N; i++) 00430 { 00431 is_xmin[i] = (i%M==0); 00432 is_xmax[i] = ((i+1)%M==0); 00433 is_ymin[i] = (i%(M*N)<M); 00434 is_ymax[i] = (i%(M*N)>=(N-1)*M); 00435 } 00436 00437 for (unsigned i=0; i<mBoxes.size(); i++) 00438 { 00439 std::set<unsigned> local_boxes; 00440 00441 local_boxes.insert(i); 00442 00443 // add the box to the left 00444 if (!is_xmin[i]) 00445 { 00446 local_boxes.insert(i-1); 00447 } 00448 00449 // add the box to the right 00450 if (!is_xmax[i]) 00451 { 00452 local_boxes.insert(i+1); 00453 } 00454 00455 // add the one below 00456 if (!is_ymin[i]) 00457 { 00458 local_boxes.insert(i-M); 00459 } 00460 00461 // add the one above 00462 if (!is_ymax[i]) 00463 { 00464 local_boxes.insert(i+M); 00465 } 00466 00467 // add the four corner boxes 00468 00469 if ( (!is_xmin[i]) && (!is_ymin[i]) ) 00470 { 00471 local_boxes.insert(i-1-M); 00472 } 00473 00474 if ( (!is_xmin[i]) && (!is_ymax[i]) ) 00475 { 00476 local_boxes.insert(i-1+M); 00477 } 00478 00479 if ( (!is_xmax[i]) && (!is_ymin[i]) ) 00480 { 00481 local_boxes.insert(i+1-M); 00482 } 00483 00484 if ( (!is_xmax[i]) && (!is_ymax[i]) ) 00485 { 00486 local_boxes.insert(i+1+M); 00487 } 00488 00489 mLocalBoxes.push_back(local_boxes); 00490 } 00491 break; 00492 } 00493 case 3: 00494 { 00495 mLocalBoxes.clear(); 00496 00497 unsigned M = mNumBoxesEachDirection(0); 00498 unsigned N = mNumBoxesEachDirection(1); 00499 unsigned P = mNumBoxesEachDirection(2); 00500 00501 std::vector<bool> is_xmin(N*M*P); // far left 00502 std::vector<bool> is_xmax(N*M*P); // far right 00503 std::vector<bool> is_ymin(N*M*P); // nearest 00504 std::vector<bool> is_ymax(N*M*P); // furthest 00505 std::vector<bool> is_zmin(N*M*P); // bottom layer 00506 std::vector<bool> is_zmax(N*M*P); // top layer 00507 00508 for (unsigned i=0; i<M*N*P; i++) 00509 { 00510 is_xmin[i] = (i%M==0); 00511 is_xmax[i] = ((i+1)%M==0); 00512 is_ymin[i] = (i%(M*N)<M); 00513 is_ymax[i] = (i%(M*N)>=(N-1)*M); 00514 is_zmin[i] = (i<M*N); 00515 is_zmax[i] = (i>=M*N*(P-1)); 00516 } 00517 00518 for (unsigned i=0; i<mBoxes.size(); i++) 00519 { 00520 std::set<unsigned> local_boxes; 00521 00522 // add itself as a local box 00523 local_boxes.insert(i); 00524 00525 // now add all 26 other neighbours..... 00526 00527 // add the box left 00528 if (!is_xmin[i]) 00529 { 00530 local_boxes.insert(i-1); 00531 00532 // plus some others towards the left 00533 if (!is_ymin[i]) 00534 { 00535 local_boxes.insert(i-1-M); 00536 } 00537 00538 if (!is_ymax[i]) 00539 { 00540 local_boxes.insert(i-1+M); 00541 } 00542 00543 if (!is_zmin[i]) 00544 { 00545 local_boxes.insert(i-1-M*N); 00546 } 00547 00548 if (!is_zmax[i]) 00549 { 00550 local_boxes.insert(i-1+M*N); 00551 } 00552 } 00553 00554 // add the box to the right 00555 if (!is_xmax[i]) 00556 { 00557 local_boxes.insert(i+1); 00558 00559 // plus some others towards the right 00560 if (!is_ymin[i]) 00561 { 00562 local_boxes.insert(i+1-M); 00563 } 00564 00565 if (!is_ymax[i]) 00566 { 00567 local_boxes.insert(i+1+M); 00568 } 00569 00570 if (!is_zmin[i]) 00571 { 00572 local_boxes.insert(i+1-M*N); 00573 } 00574 00575 if (!is_zmax[i]) 00576 { 00577 local_boxes.insert(i+1+M*N); 00578 } 00579 } 00580 00581 // add the boxes next along the y axis 00582 if (!is_ymin[i]) 00583 { 00584 local_boxes.insert(i-M); 00585 00586 // and more in this plane 00587 if (!is_zmin[i]) 00588 { 00589 local_boxes.insert(i-M-M*N); 00590 } 00591 00592 if (!is_zmax[i]) 00593 { 00594 local_boxes.insert(i-M+M*N); 00595 } 00596 } 00597 00598 // add the boxes next along the y axis 00599 if (!is_ymax[i]) 00600 { 00601 local_boxes.insert(i+M); 00602 00603 // and more in this plane 00604 if (!is_zmin[i]) 00605 { 00606 local_boxes.insert(i+M-M*N); 00607 } 00608 00609 if (!is_zmax[i]) 00610 { 00611 local_boxes.insert(i+M+M*N); 00612 } 00613 } 00614 00615 // add the box directly above 00616 if (!is_zmin[i]) 00617 { 00618 local_boxes.insert(i-N*M); 00619 } 00620 00621 // add the box directly below 00622 if (!is_zmax[i]) 00623 { 00624 local_boxes.insert(i+N*M); 00625 } 00626 00627 // finally, the 8 corners are left 00628 00629 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmin[i]) ) 00630 { 00631 local_boxes.insert(i-1-M-M*N); 00632 } 00633 00634 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmax[i]) ) 00635 { 00636 local_boxes.insert(i-1-M+M*N); 00637 } 00638 00639 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmin[i]) ) 00640 { 00641 local_boxes.insert(i-1+M-M*N); 00642 } 00643 00644 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmax[i]) ) 00645 { 00646 local_boxes.insert(i-1+M+M*N); 00647 } 00648 00649 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmin[i]) ) 00650 { 00651 local_boxes.insert(i+1-M-M*N); 00652 } 00653 00654 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmax[i]) ) 00655 { 00656 local_boxes.insert(i+1-M+M*N); 00657 } 00658 00659 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmin[i]) ) 00660 { 00661 local_boxes.insert(i+1+M-M*N); 00662 } 00663 00664 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmax[i]) ) 00665 { 00666 local_boxes.insert(i+1+M+M*N); 00667 } 00668 00669 mLocalBoxes.push_back(local_boxes); 00670 } 00671 break; 00672 } 00673 default: 00674 NEVER_REACHED; 00675 } 00676 } 00677 00678 template<unsigned DIM> 00679 std::set<unsigned> BoxCollection<DIM>::GetLocalBoxes(unsigned boxIndex) 00680 { 00681 assert(boxIndex < mLocalBoxes.size()); 00682 return mLocalBoxes[boxIndex]; 00683 } 00684 00685 template<unsigned DIM> 00686 void BoxCollection<DIM>::CalculateNodePairs(std::vector<Node<DIM>*>& rNodes, std::set<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours) 00687 { 00688 rNodePairs.clear(); 00689 rNodeNeighbours.clear(); 00690 00691 // Create an empty set of neighbours for each node 00692 for (unsigned node_index=0; node_index<rNodes.size(); node_index++) 00693 { 00694 rNodeNeighbours[node_index] = std::set<unsigned>(); 00695 } 00696 00697 for (unsigned node_index=0; node_index<rNodes.size(); node_index++) 00698 { 00699 // Get the box containing this node 00700 unsigned box_index = CalculateContainingBox(rNodes[node_index]); 00701 00702 // Get the local boxes to this node 00703 std::set<unsigned> local_boxes_indices = GetLocalBoxes(box_index); 00704 00705 // Loop over all the local boxes 00706 for (std::set<unsigned>::iterator box_iter = local_boxes_indices.begin(); 00707 box_iter != local_boxes_indices.end(); 00708 box_iter++) 00709 { 00710 // Get the set of nodes contained in this box 00711 std::set< Node<DIM>* >& r_contained_nodes = mBoxes[*box_iter].rGetNodesContained(); 00712 00713 // Loop over these nodes 00714 for (typename std::set<Node<DIM>*>::iterator node_iter = r_contained_nodes.begin(); 00715 node_iter != r_contained_nodes.end(); 00716 ++node_iter) 00717 { 00718 // Get the index of the other node 00719 unsigned other_node_index = (*node_iter)->GetIndex(); 00720 00721 // If we're in the same box, then take care not to store the node pair twice 00722 if (*box_iter == box_index) 00723 { 00724 if (other_node_index > node_index) 00725 { 00726 rNodePairs.insert(std::pair<Node<DIM>*, Node<DIM>*>(rNodes[node_index], rNodes[other_node_index])); 00727 rNodeNeighbours[node_index].insert(other_node_index); 00728 rNodeNeighbours[other_node_index].insert(node_index); 00729 } 00730 } 00731 else 00732 { 00733 rNodePairs.insert(std::pair<Node<DIM>*, Node<DIM>*>(rNodes[node_index], rNodes[other_node_index])); 00734 rNodeNeighbours[node_index].insert(other_node_index); 00735 rNodeNeighbours[other_node_index].insert(node_index); 00736 } 00737 } 00738 } 00739 } 00740 } 00741 00743 // Explicit instantiation 00745 00746 template class Box<1>; 00747 template class Box<2>; 00748 template class Box<3>; 00749 template class BoxCollection<1>; 00750 template class BoxCollection<2>; 00751 template class BoxCollection<3>;