BoxCollection.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "BoxCollection.hpp"
00036 #include "Exception.hpp"
00037
00039
00041
00042
00043 template<unsigned DIM>
00044 const double BoxCollection<DIM>::msFudge = 5e-14;
00045
00046 template<unsigned DIM>
00047 BoxCollection<DIM>::BoxCollection(double boxWidth, c_vector<double, 2*DIM> domainSize, bool isPeriodicInX)
00048 : mDomainSize(domainSize),
00049 mBoxWidth(boxWidth),
00050 mIsPeriodicInX(isPeriodicInX)
00051 {
00052
00053 if (isPeriodicInX)
00054 {
00055 assert(DIM==2);
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065 unsigned num_boxes = 1;
00066 std::vector<unsigned> coefficients;
00067 coefficients.push_back(1);
00068
00069 for (unsigned i=0; i<DIM; i++)
00070 {
00071 mNumBoxesEachDirection(i) = (unsigned) floor((domainSize(2*i+1) - domainSize(2*i))/boxWidth + msFudge) + 1;
00072 num_boxes *= mNumBoxesEachDirection(i);
00073 coefficients.push_back(coefficients[i]*mNumBoxesEachDirection(i));
00074 }
00075
00076 for (unsigned box_index=0; box_index<num_boxes; box_index++)
00077 {
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 c_vector<unsigned, DIM+1> current_box_indices;
00097 current_box_indices[0] = 0;
00098
00099 for (unsigned i=0; i<DIM; i++)
00100 {
00101 unsigned temp = 0;
00102 for (unsigned j=1; j<i; j++)
00103 {
00104 temp += coefficients[j]*current_box_indices[j-1];
00105 }
00106 current_box_indices[i+1] = (box_index%coefficients[i+1] - temp)/coefficients[i];
00107 }
00108
00109
00110
00111
00112
00113 c_vector<double, 2*DIM> box_coords;
00114 for (unsigned l=0; l<DIM; l++)
00115 {
00116 box_coords(2*l) = domainSize(2*l) + current_box_indices(l+1)*boxWidth;
00117 box_coords(2*l+1) = domainSize(2*l) + (current_box_indices(l+1)+1)*boxWidth;
00118 }
00119
00120 Box<DIM> new_box(box_coords);
00121 mBoxes.push_back(new_box);
00122 }
00123
00124
00125 assert(num_boxes == mBoxes.size());
00126 }
00127
00128 template<unsigned DIM>
00129 void BoxCollection<DIM>::EmptyBoxes()
00130 {
00131 for (unsigned i=0; i<mBoxes.size(); i++)
00132 {
00133 mBoxes[i].ClearNodes();
00134 }
00135 }
00136
00137 template<unsigned DIM>
00138 unsigned BoxCollection<DIM>::CalculateContainingBox(Node<DIM>* pNode)
00139 {
00140
00141 c_vector<double, DIM> location = pNode->rGetLocation();
00142 return CalculateContainingBox(location);
00143 }
00144
00145
00146 template<unsigned DIM>
00147 unsigned BoxCollection<DIM>::CalculateContainingBox(c_vector<double, DIM>& rLocation)
00148 {
00149
00150 for (unsigned i=0; i<DIM; i++)
00151 {
00152 if ( (rLocation[i] < mDomainSize(2*i)) || (rLocation[i] > mDomainSize(2*i+1)) )
00153 {
00154 EXCEPTION("The point provided is outside all of the boxes");
00155 }
00156 }
00157
00158
00159 c_vector<unsigned, DIM> containing_box_indices;
00160 for (unsigned i=0; i<DIM; i++)
00161 {
00162 containing_box_indices[i] = (unsigned) floor((rLocation[i] - mDomainSize(2*i) + msFudge)/mBoxWidth);
00163 }
00164
00165
00166 unsigned containing_box_index = 0;
00167 for (unsigned i=0; i<DIM; i++)
00168 {
00169 unsigned temp = 1;
00170 for (unsigned j=0; j<i; j++)
00171 {
00172 temp *= mNumBoxesEachDirection(j);
00173 }
00174 containing_box_index += temp*containing_box_indices[i];
00175 }
00176
00177
00178 assert(containing_box_index < mBoxes.size());
00179
00180 return containing_box_index;
00181 }
00182
00183 template<unsigned DIM>
00184 Box<DIM>& BoxCollection<DIM>::rGetBox(unsigned boxIndex)
00185 {
00186 assert(boxIndex < mBoxes.size());
00187 return mBoxes[boxIndex];
00188 }
00189
00190 template<unsigned DIM>
00191 unsigned BoxCollection<DIM>::GetNumBoxes()
00192 {
00193 return mBoxes.size();
00194 }
00195
00196 template<unsigned DIM>
00197 void BoxCollection<DIM>::SetupLocalBoxesHalfOnly()
00198 {
00199 switch (DIM)
00200 {
00201 case 1:
00202 {
00203
00204 mLocalBoxes.clear();
00205 for (unsigned box_index=0; box_index<mBoxes.size(); box_index++)
00206 {
00207 std::set<unsigned> local_boxes;
00208
00209
00210 local_boxes.insert(box_index);
00211
00212
00213 if (box_index < mNumBoxesEachDirection(0)-1)
00214 {
00215 local_boxes.insert(box_index+1);
00216 }
00217 mLocalBoxes.push_back(local_boxes);
00218 }
00219 break;
00220 }
00221 case 2:
00222 {
00223
00224 mLocalBoxes.clear();
00225 for (unsigned box_index=0; box_index<mBoxes.size(); box_index++)
00226 {
00227 std::set<unsigned> local_boxes;
00228
00229
00230 local_boxes.insert(box_index);
00231
00232
00233 if (box_index < mBoxes.size() - mNumBoxesEachDirection(0))
00234 {
00235 local_boxes.insert(box_index + mNumBoxesEachDirection(0));
00236
00237
00238 if (box_index % mNumBoxesEachDirection(0) != 0)
00239 {
00240 local_boxes.insert(box_index + mNumBoxesEachDirection(0) - 1);
00241 }
00242
00243 else if ( (box_index % mNumBoxesEachDirection(0) == 0) && (mIsPeriodicInX) )
00244 {
00245 local_boxes.insert(box_index + 2* mNumBoxesEachDirection(0) - 1);
00246 }
00247
00248 }
00249
00250 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00251 {
00252 local_boxes.insert(box_index + 1);
00253
00254
00255 if (box_index < mBoxes.size() - mNumBoxesEachDirection(0))
00256 {
00257 local_boxes.insert(box_index + mNumBoxesEachDirection(0) + 1);
00258 }
00259 }
00260
00261 else if ( (box_index % mNumBoxesEachDirection(0) == mNumBoxesEachDirection(0)-1) && (mIsPeriodicInX) )
00262 {
00263 local_boxes.insert(box_index - mNumBoxesEachDirection(0) + 1);
00264
00265 if (box_index < mBoxes.size() - mNumBoxesEachDirection(0))
00266 {
00267 local_boxes.insert(box_index + 1);
00268 }
00269 }
00270
00271 mLocalBoxes.push_back(local_boxes);
00272 }
00273 break;
00274 }
00275 case 3:
00276 {
00277
00278 mLocalBoxes.clear();
00279 unsigned num_boxes_xy = mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1);
00280
00281 for (unsigned box_index=0; box_index<mBoxes.size(); box_index++)
00282 {
00283 std::set<unsigned> local_boxes;
00284
00285
00286 local_boxes.insert(box_index);
00287
00288
00289 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00290 {
00291 local_boxes.insert(box_index + mNumBoxesEachDirection(0));
00292
00293
00294 if (box_index % mNumBoxesEachDirection(0) != 0)
00295 {
00296 local_boxes.insert(box_index + mNumBoxesEachDirection(0) - 1);
00297 }
00298 }
00299
00300 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00301 {
00302 local_boxes.insert(box_index + 1);
00303
00304
00305 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00306 {
00307 local_boxes.insert(box_index + mNumBoxesEachDirection(0) + 1);
00308 }
00309 }
00310
00311 if (box_index < mBoxes.size() - num_boxes_xy)
00312 {
00313 local_boxes.insert(box_index + num_boxes_xy);
00314
00315
00316 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00317 {
00318 local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0));
00319
00320
00321 if (box_index % mNumBoxesEachDirection(0) != 0)
00322 {
00323 local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0) - 1);
00324 }
00325 }
00326
00327 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00328 {
00329 local_boxes.insert(box_index + num_boxes_xy + 1);
00330
00331
00332 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00333 {
00334 local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0) + 1);
00335 }
00336 }
00337 }
00338
00339 if (box_index >= num_boxes_xy)
00340 {
00341
00342 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00343 {
00344 local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0));
00345
00346
00347 if (box_index % mNumBoxesEachDirection(0) != 0)
00348 {
00349 local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0) - 1);
00350 }
00351 }
00352
00353 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00354 {
00355 local_boxes.insert(box_index - num_boxes_xy + 1);
00356
00357
00358 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00359 {
00360 local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0) + 1);
00361 }
00362 }
00363 }
00364 mLocalBoxes.push_back(local_boxes);
00365 }
00366 break;
00367 }
00368 default:
00369 NEVER_REACHED;
00370 }
00371 }
00372
00373
00374
00375 template<unsigned DIM>
00376 void BoxCollection<DIM>::SetupAllLocalBoxes()
00377 {
00378 switch (DIM)
00379 {
00380 case 1:
00381 {
00382 for (unsigned i=0; i<mBoxes.size(); i++)
00383 {
00384 std::set<unsigned> local_boxes;
00385
00386 local_boxes.insert(i);
00387
00388
00389 if (i!=0)
00390 {
00391 local_boxes.insert(i-1);
00392 }
00393 if (i+1 != mNumBoxesEachDirection(0))
00394 {
00395 local_boxes.insert(i+1);
00396 }
00397
00398 mLocalBoxes.push_back(local_boxes);
00399 }
00400 break;
00401 }
00402 case 2:
00403 {
00404 mLocalBoxes.clear();
00405
00406 unsigned M = mNumBoxesEachDirection(0);
00407 unsigned N = mNumBoxesEachDirection(1);
00408
00409 std::vector<bool> is_xmin(N*M);
00410 std::vector<bool> is_xmax(N*M);
00411 std::vector<bool> is_ymin(N*M);
00412 std::vector<bool> is_ymax(N*M);
00413
00414 for (unsigned i=0; i<M*N; i++)
00415 {
00416 is_xmin[i] = (i%M==0);
00417 is_xmax[i] = ((i+1)%M==0);
00418 is_ymin[i] = (i%(M*N)<M);
00419 is_ymax[i] = (i%(M*N)>=(N-1)*M);
00420 }
00421
00422 for (unsigned i=0; i<mBoxes.size(); i++)
00423 {
00424 std::set<unsigned> local_boxes;
00425
00426 local_boxes.insert(i);
00427
00428
00429 if (!is_xmin[i])
00430 {
00431 local_boxes.insert(i-1);
00432 }
00433 else
00434 {
00435 if(mIsPeriodicInX)
00436 {
00437 local_boxes.insert(i+M-1);
00438 }
00439 }
00440
00441
00442 if (!is_xmax[i])
00443 {
00444 local_boxes.insert(i+1);
00445 }
00446 else
00447 {
00448 if(mIsPeriodicInX)
00449 {
00450 local_boxes.insert(i-M+1);
00451 }
00452 }
00453
00454
00455 if (!is_ymin[i])
00456 {
00457 local_boxes.insert(i-M);
00458 }
00459
00460
00461 if (!is_ymax[i])
00462 {
00463 local_boxes.insert(i+M);
00464 }
00465
00466
00467
00468 if ( (!is_xmin[i]) && (!is_ymin[i]) )
00469 {
00470 local_boxes.insert(i-1-M);
00471 }
00472 if ( (!is_xmin[i]) && (!is_ymax[i]) )
00473 {
00474 local_boxes.insert(i-1+M);
00475 }
00476 if ( (!is_xmax[i]) && (!is_ymin[i]) )
00477 {
00478 local_boxes.insert(i+1-M);
00479 }
00480 if ( (!is_xmax[i]) && (!is_ymax[i]) )
00481 {
00482 local_boxes.insert(i+1+M);
00483 }
00484
00485
00486 if(mIsPeriodicInX)
00487 {
00488 if( (is_xmin[i]) && (!is_ymin[i]) )
00489 {
00490 local_boxes.insert(i-1);
00491 }
00492 if ( (is_xmin[i]) && (!is_ymax[i]) )
00493 {
00494 local_boxes.insert(i-1+2*M);
00495 }
00496 if ( (is_xmax[i]) && (!is_ymin[i]) )
00497 {
00498 local_boxes.insert(i+1-2*M);
00499 }
00500 if ( (is_xmax[i]) && (!is_ymax[i]) )
00501 {
00502 local_boxes.insert(i+1);
00503 }
00504 }
00505
00506 mLocalBoxes.push_back(local_boxes);
00507 }
00508 break;
00509 }
00510 case 3:
00511 {
00512 mLocalBoxes.clear();
00513
00514 unsigned M = mNumBoxesEachDirection(0);
00515 unsigned N = mNumBoxesEachDirection(1);
00516 unsigned P = mNumBoxesEachDirection(2);
00517
00518 std::vector<bool> is_xmin(N*M*P);
00519 std::vector<bool> is_xmax(N*M*P);
00520 std::vector<bool> is_ymin(N*M*P);
00521 std::vector<bool> is_ymax(N*M*P);
00522 std::vector<bool> is_zmin(N*M*P);
00523 std::vector<bool> is_zmax(N*M*P);
00524
00525 for (unsigned i=0; i<M*N*P; i++)
00526 {
00527 is_xmin[i] = (i%M==0);
00528 is_xmax[i] = ((i+1)%M==0);
00529 is_ymin[i] = (i%(M*N)<M);
00530 is_ymax[i] = (i%(M*N)>=(N-1)*M);
00531 is_zmin[i] = (i<M*N);
00532 is_zmax[i] = (i>=M*N*(P-1));
00533 }
00534
00535 for (unsigned i=0; i<mBoxes.size(); i++)
00536 {
00537 std::set<unsigned> local_boxes;
00538
00539
00540 local_boxes.insert(i);
00541
00542
00543
00544
00545 if (!is_xmin[i])
00546 {
00547 local_boxes.insert(i-1);
00548
00549
00550 if (!is_ymin[i])
00551 {
00552 local_boxes.insert(i-1-M);
00553 }
00554
00555 if (!is_ymax[i])
00556 {
00557 local_boxes.insert(i-1+M);
00558 }
00559
00560 if (!is_zmin[i])
00561 {
00562 local_boxes.insert(i-1-M*N);
00563 }
00564
00565 if (!is_zmax[i])
00566 {
00567 local_boxes.insert(i-1+M*N);
00568 }
00569 }
00570
00571
00572 if (!is_xmax[i])
00573 {
00574 local_boxes.insert(i+1);
00575
00576
00577 if (!is_ymin[i])
00578 {
00579 local_boxes.insert(i+1-M);
00580 }
00581
00582 if (!is_ymax[i])
00583 {
00584 local_boxes.insert(i+1+M);
00585 }
00586
00587 if (!is_zmin[i])
00588 {
00589 local_boxes.insert(i+1-M*N);
00590 }
00591
00592 if (!is_zmax[i])
00593 {
00594 local_boxes.insert(i+1+M*N);
00595 }
00596 }
00597
00598
00599 if (!is_ymin[i])
00600 {
00601 local_boxes.insert(i-M);
00602
00603
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
00616 if (!is_ymax[i])
00617 {
00618 local_boxes.insert(i+M);
00619
00620
00621 if (!is_zmin[i])
00622 {
00623 local_boxes.insert(i+M-M*N);
00624 }
00625
00626 if (!is_zmax[i])
00627 {
00628 local_boxes.insert(i+M+M*N);
00629 }
00630 }
00631
00632
00633 if (!is_zmin[i])
00634 {
00635 local_boxes.insert(i-N*M);
00636 }
00637
00638
00639 if (!is_zmax[i])
00640 {
00641 local_boxes.insert(i+N*M);
00642 }
00643
00644
00645
00646 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmin[i]) )
00647 {
00648 local_boxes.insert(i-1-M-M*N);
00649 }
00650
00651 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmax[i]) )
00652 {
00653 local_boxes.insert(i-1-M+M*N);
00654 }
00655
00656 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmin[i]) )
00657 {
00658 local_boxes.insert(i-1+M-M*N);
00659 }
00660
00661 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmax[i]) )
00662 {
00663 local_boxes.insert(i-1+M+M*N);
00664 }
00665
00666 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmin[i]) )
00667 {
00668 local_boxes.insert(i+1-M-M*N);
00669 }
00670
00671 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmax[i]) )
00672 {
00673 local_boxes.insert(i+1-M+M*N);
00674 }
00675
00676 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmin[i]) )
00677 {
00678 local_boxes.insert(i+1+M-M*N);
00679 }
00680
00681 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmax[i]) )
00682 {
00683 local_boxes.insert(i+1+M+M*N);
00684 }
00685
00686 mLocalBoxes.push_back(local_boxes);
00687 }
00688 break;
00689 }
00690 default:
00691 NEVER_REACHED;
00692 }
00693 }
00694
00695 template<unsigned DIM>
00696 std::set<unsigned> BoxCollection<DIM>::GetLocalBoxes(unsigned boxIndex)
00697 {
00698 assert(boxIndex < mLocalBoxes.size());
00699 return mLocalBoxes[boxIndex];
00700 }
00701
00702 template<unsigned DIM>
00703 const c_vector<double, 2*DIM>& BoxCollection<DIM>::rGetDomainSize() const
00704 {
00705 return mDomainSize;
00706 }
00707
00708 template<unsigned DIM>
00709 void BoxCollection<DIM>::CalculateNodePairs(std::vector<Node<DIM>*>& rNodes, std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
00710 {
00711 rNodePairs.clear();
00712 rNodeNeighbours.clear();
00713
00714
00715 for (unsigned node_index=0; node_index<rNodes.size(); node_index++)
00716 {
00717 rNodeNeighbours[node_index] = std::set<unsigned>();
00718 }
00719
00720 for (unsigned i=0; i<rNodes.size(); i++)
00721 {
00722 unsigned node_index = rNodes[i]->GetIndex();
00723
00724
00725 unsigned box_index = CalculateContainingBox(rNodes[i]);
00726
00727
00728 std::set<unsigned> local_boxes_indices = GetLocalBoxes(box_index);
00729
00730
00731 for (std::set<unsigned>::iterator box_iter = local_boxes_indices.begin();
00732 box_iter != local_boxes_indices.end();
00733 box_iter++)
00734 {
00735
00736 std::set< Node<DIM>* >& r_contained_nodes = mBoxes[*box_iter].rGetNodesContained();
00737
00738
00739 for (typename std::set<Node<DIM>*>::iterator node_iter = r_contained_nodes.begin();
00740 node_iter != r_contained_nodes.end();
00741 ++node_iter)
00742 {
00743
00744 unsigned other_node_index = (*node_iter)->GetIndex();
00745
00746
00747 if (*box_iter == box_index)
00748 {
00749 if (other_node_index > rNodes[i]->GetIndex())
00750 {
00751 rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>(rNodes[i], (*node_iter)));
00752 rNodeNeighbours[node_index].insert(other_node_index);
00753 rNodeNeighbours[other_node_index].insert(node_index);
00754 }
00755 }
00756 else
00757 {
00758 rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>(rNodes[i], (*node_iter)));
00759 rNodeNeighbours[node_index].insert(other_node_index);
00760 rNodeNeighbours[other_node_index].insert(node_index);
00761 }
00762 }
00763 }
00764 }
00765 }
00766
00768
00770
00771 template class BoxCollection<1>;
00772 template class BoxCollection<2>;
00773 template class BoxCollection<3>;