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 "DistributedBoxCollection.hpp"
00036 #include "Exception.hpp"
00037 #include "MathsCustomFunctions.hpp"
00038
00039
00040 template<unsigned DIM>
00041 const double DistributedBoxCollection<DIM>::msFudge = 5e-14;
00042
00043 template<unsigned DIM>
00044 DistributedBoxCollection<DIM>::DistributedBoxCollection(double boxWidth, c_vector<double, 2*DIM> domainSize, bool isPeriodicInX, int localRows)
00045 : mBoxWidth(boxWidth),
00046 mIsPeriodicInX(isPeriodicInX),
00047 mAreLocalBoxesSet(false),
00048 mCalculateNodeNeighbours(true)
00049 {
00050
00051 if (isPeriodicInX)
00052 {
00053 assert(DIM==2 && PetscTools::IsSequential());
00054 }
00055
00056
00057 for (unsigned i=0; i<DIM; i++)
00058 {
00059 double r = fmod((domainSize[2*i+1]-domainSize[2*i]), boxWidth);
00060 if (r > 0.0)
00061 {
00062 domainSize[2*i+1] += boxWidth - r;
00063 }
00064 }
00065
00066 mDomainSize = domainSize;
00067
00068
00069 mNumBoxesEachDirection = scalar_vector<unsigned>(DIM, 0u);
00070
00071 for (unsigned i=0; i<DIM; i++)
00072 {
00073 double counter = mDomainSize(2*i);
00074 while (counter + msFudge < mDomainSize(2*i+1))
00075 {
00076 mNumBoxesEachDirection(i)++;
00077 counter += mBoxWidth;
00078 }
00079 }
00080
00081
00082 if (mNumBoxesEachDirection(DIM-1) < PetscTools::GetNumProcs())
00083 {
00084 mDomainSize[2*DIM - 1] += (PetscTools::GetNumProcs() - mNumBoxesEachDirection(DIM-1))*mBoxWidth;
00085 mNumBoxesEachDirection(DIM-1) = PetscTools::GetNumProcs();
00086 }
00087
00088
00089 mpDistributedBoxStackFactory = new DistributedVectorFactory(mNumBoxesEachDirection(DIM-1), localRows);
00090
00091
00092 mNumBoxesInAFace = 1;
00093 for (unsigned i=1; i<DIM; i++)
00094 {
00095 mNumBoxesInAFace *= mNumBoxesEachDirection(i-1);
00096 }
00097
00098 unsigned num_boxes = mNumBoxesInAFace * (mpDistributedBoxStackFactory->GetHigh() - mpDistributedBoxStackFactory->GetLow());
00099
00100 mMinBoxIndex = mpDistributedBoxStackFactory->GetLow() * mNumBoxesInAFace;
00101 mMaxBoxIndex = mpDistributedBoxStackFactory->GetHigh() * mNumBoxesInAFace - 1;
00102
00103
00104
00105
00106
00107
00108 c_vector<double, 2*DIM> arbitrary_location;
00109 for (unsigned i=0; i<num_boxes; i++)
00110 {
00111 Box<DIM> new_box(arbitrary_location);
00112 mBoxes.push_back(new_box);
00113
00114 unsigned global_index = mMinBoxIndex + i;
00115 mBoxesMapping[global_index] = mBoxes.size() - 1;
00116 }
00117
00118 mNumBoxes = mNumBoxesInAFace * mNumBoxesEachDirection(DIM-1);
00119 }
00120
00121 template<unsigned DIM>
00122 DistributedBoxCollection<DIM>::~DistributedBoxCollection()
00123 {
00124 delete mpDistributedBoxStackFactory;
00125 }
00126
00127 template<unsigned DIM>
00128 void DistributedBoxCollection<DIM>::EmptyBoxes()
00129 {
00130 for (unsigned i=0; i<mBoxes.size(); i++)
00131 {
00132 mBoxes[i].ClearNodes();
00133 }
00134 for (unsigned i=0; i<mHaloBoxes.size(); i++)
00135 {
00136 mHaloBoxes[i].ClearNodes();
00137 }
00138 }
00139
00140 template<unsigned DIM>
00141 void DistributedBoxCollection<DIM>::SetupHaloBoxes()
00142 {
00143
00144 unsigned Hi = mpDistributedBoxStackFactory->GetHigh();
00145 unsigned Lo = mpDistributedBoxStackFactory->GetLow();
00146
00147
00148 if (!PetscTools::AmTopMost())
00149 {
00150 for (unsigned i=0; i < mNumBoxesInAFace; i++)
00151 {
00152 c_vector<double, 2*DIM> arbitrary_location;
00153 Box<DIM> new_box(arbitrary_location);
00154 mHaloBoxes.push_back(new_box);
00155
00156 unsigned global_index = Hi * mNumBoxesInAFace + i;
00157 mHaloBoxesMapping[global_index] = mHaloBoxes.size()-1;
00158 mHalosRight.push_back(global_index - mNumBoxesInAFace);
00159 }
00160 }
00161
00162
00163 if (!PetscTools::AmMaster())
00164 {
00165 for (unsigned i=0; i< mNumBoxesInAFace; i++)
00166 {
00167 c_vector<double, 2*DIM> arbitrary_location;
00168 Box<DIM> new_box(arbitrary_location);
00169 mHaloBoxes.push_back(new_box);
00170
00171 unsigned global_index = (Lo - 1) * mNumBoxesInAFace + i;
00172 mHaloBoxesMapping[global_index] = mHaloBoxes.size() - 1;
00173
00174 mHalosLeft.push_back(global_index + mNumBoxesInAFace);
00175 }
00176 }
00177 }
00178
00179 template<unsigned DIM>
00180 void DistributedBoxCollection<DIM>::UpdateHaloBoxes()
00181 {
00182 mHaloNodesLeft.clear();
00183 for (unsigned i=0; i<mHalosLeft.size(); i++)
00184 {
00185 for (typename std::set<Node<DIM>* >::iterator iter=this->rGetBox(mHalosLeft[i]).rGetNodesContained().begin();
00186 iter!=this->rGetBox(mHalosLeft[i]).rGetNodesContained().end();
00187 iter++)
00188 {
00189 mHaloNodesLeft.push_back((*iter)->GetIndex());
00190 }
00191 }
00192
00193
00194 mHaloNodesRight.clear();
00195 for (unsigned i=0; i<mHalosRight.size(); i++)
00196 {
00197 for (typename std::set<Node<DIM>* >::iterator iter=this->rGetBox(mHalosRight[i]).rGetNodesContained().begin();
00198 iter!=this->rGetBox(mHalosRight[i]).rGetNodesContained().end();
00199 iter++)
00200 {
00201 mHaloNodesRight.push_back((*iter)->GetIndex());
00202 }
00203 }
00204 }
00205
00206 template<unsigned DIM>
00207 unsigned DistributedBoxCollection<DIM>::GetNumLocalRows() const
00208 {
00209 return mpDistributedBoxStackFactory->GetHigh() - mpDistributedBoxStackFactory->GetLow();
00210 }
00211
00212 template<unsigned DIM>
00213 bool DistributedBoxCollection<DIM>::GetBoxOwnership(unsigned globalIndex)
00214 {
00215 return (!(globalIndex<mMinBoxIndex) && !(mMaxBoxIndex<globalIndex));
00216 }
00217
00218 template<unsigned DIM>
00219 bool DistributedBoxCollection<DIM>::GetHaloBoxOwnership(unsigned globalIndex)
00220 {
00221 bool is_halo_right = ((globalIndex > mMaxBoxIndex) && !(globalIndex > mMaxBoxIndex + mNumBoxesInAFace));
00222 bool is_halo_left = ((globalIndex < mMinBoxIndex) && !(globalIndex < mMinBoxIndex - mNumBoxesInAFace));
00223
00224 return (PetscTools::IsParallel() && (is_halo_right || is_halo_left));
00225 }
00226
00227 template<unsigned DIM>
00228 bool DistributedBoxCollection<DIM>::IsInteriorBox(unsigned globalIndex)
00229 {
00230 bool is_on_boundary = !(globalIndex < mMaxBoxIndex - mNumBoxesInAFace) || (globalIndex < mMinBoxIndex + mNumBoxesInAFace);
00231
00232 return (PetscTools::IsSequential() || !(is_on_boundary));
00233 }
00234
00235 template<unsigned DIM>
00236 unsigned DistributedBoxCollection<DIM>::CalculateGlobalIndex(c_vector<unsigned, DIM> coordinateIndices)
00237 {
00238 unsigned containing_box_index = 0;
00239 for (unsigned i=0; i<DIM; i++)
00240 {
00241 unsigned temp = 1;
00242 for (unsigned j=0; j<i; j++)
00243 {
00244 temp *= mNumBoxesEachDirection(j);
00245 }
00246 containing_box_index += temp*coordinateIndices[i];
00247 }
00248
00249 return containing_box_index;
00250 }
00251
00252 template<unsigned DIM>
00253 unsigned DistributedBoxCollection<DIM>::CalculateContainingBox(Node<DIM>* pNode)
00254 {
00255
00256 c_vector<double, DIM> location = pNode->rGetLocation();
00257 return CalculateContainingBox(location);
00258 }
00259
00260
00261 template<unsigned DIM>
00262 unsigned DistributedBoxCollection<DIM>::CalculateContainingBox(c_vector<double, DIM>& rLocation)
00263 {
00264
00265 for (unsigned i=0; i<DIM; i++)
00266 {
00267 if ( (rLocation[i] < mDomainSize(2*i)) || !(rLocation[i] < mDomainSize(2*i+1)) )
00268 {
00269 EXCEPTION("The point provided is outside all of the boxes");
00270 }
00271 }
00272
00273
00274 c_vector<unsigned, DIM> containing_box_indices = scalar_vector<unsigned>(DIM, 0u);
00275 for (unsigned i=0; i<DIM; i++)
00276 {
00277 double box_counter = mDomainSize(2*i);
00278 while (!((box_counter + mBoxWidth) > rLocation[i] + msFudge))
00279 {
00280 containing_box_indices[i]++;
00281 box_counter += mBoxWidth;
00282 }
00283 }
00284
00285
00286 unsigned containing_box_index = 0;
00287 for (unsigned i=0; i<DIM; i++)
00288 {
00289 unsigned temp = 1;
00290 for (unsigned j=0; j<i; j++)
00291 {
00292 temp *= mNumBoxesEachDirection(j);
00293 }
00294 containing_box_index += temp*containing_box_indices[i];
00295 }
00296
00297
00298 assert(containing_box_index < mNumBoxes);
00299
00300 return containing_box_index;
00301 }
00302
00303 template<unsigned DIM>
00304 c_vector<unsigned, DIM> DistributedBoxCollection<DIM>::CalculateCoordinateIndices(unsigned globalIndex)
00305 {
00306 c_vector<unsigned, DIM> indices;
00307
00308 switch(DIM)
00309 {
00310 case 1:
00311 {
00312 indices[0]=globalIndex;
00313 break;
00314 }
00315 case 2:
00316 {
00317 unsigned remainder=globalIndex % mNumBoxesEachDirection(0);
00318 indices[0]=remainder;
00319 indices[1]=(unsigned)(globalIndex/mNumBoxesEachDirection(0));
00320 break;
00321 }
00322
00323 case 3:
00324 {
00325 unsigned remainder1=globalIndex % (mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1));
00326 unsigned remainder2=remainder1 % mNumBoxesEachDirection(0);
00327 indices[0]=remainder2;
00328 indices[1]=((globalIndex-indices[0])/mNumBoxesEachDirection(0))%mNumBoxesEachDirection(1);
00329 indices[2]=((globalIndex-indices[0]-mNumBoxesEachDirection(0)*indices[1])/(mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1)));
00330 break;
00331 }
00332 default:
00333 {
00334 NEVER_REACHED;
00335 }
00336 }
00337
00338 return indices;
00339 }
00340
00341 template<unsigned DIM>
00342 Box<DIM>& DistributedBoxCollection<DIM>::rGetBox(unsigned boxIndex)
00343 {
00344 assert(!(boxIndex<mMinBoxIndex) && !(mMaxBoxIndex<boxIndex));
00345 return mBoxes[boxIndex-mMinBoxIndex];
00346 }
00347
00348 template<unsigned DIM>
00349 Box<DIM>& DistributedBoxCollection<DIM>::rGetHaloBox(unsigned boxIndex)
00350 {
00351 assert(GetHaloBoxOwnership(boxIndex));
00352
00353 unsigned local_index = mHaloBoxesMapping.find(boxIndex)->second;
00354
00355 return mHaloBoxes[local_index];
00356 }
00357
00358 template<unsigned DIM>
00359 unsigned DistributedBoxCollection<DIM>::GetNumBoxes()
00360 {
00361 return mNumBoxes;
00362 }
00363
00364 template<unsigned DIM>
00365 unsigned DistributedBoxCollection<DIM>::GetNumLocalBoxes()
00366 {
00367 return mBoxes.size();
00368 }
00369
00370 template<unsigned DIM>
00371 c_vector<double, 2*DIM> DistributedBoxCollection<DIM>::rGetDomainSize() const
00372 {
00373 return mDomainSize;
00374 }
00375
00376 template<unsigned DIM>
00377 bool DistributedBoxCollection<DIM>::GetAreLocalBoxesSet() const
00378 {
00379 return mAreLocalBoxesSet;
00380 }
00381
00382 template<unsigned DIM>
00383 double DistributedBoxCollection<DIM>::GetBoxWidth() const
00384 {
00385 return mBoxWidth;
00386 }
00387
00388 template<unsigned DIM>
00389 unsigned DistributedBoxCollection<DIM>::GetNumRowsOfBoxes() const
00390 {
00391 return mpDistributedBoxStackFactory->GetHigh() - mpDistributedBoxStackFactory->GetLow();
00392 }
00393
00394 template<unsigned DIM>
00395 int DistributedBoxCollection<DIM>::LoadBalance(std::vector<int> localDistribution)
00396 {
00397 MPI_Status status;
00398
00399 int proc_right = (PetscTools::AmTopMost()) ? MPI_PROC_NULL : (int)PetscTools::GetMyRank() + 1;
00400 int proc_left = (PetscTools::AmMaster()) ? MPI_PROC_NULL : (int)PetscTools::GetMyRank() - 1;
00401
00402
00403 int new_rows = localDistribution.size();
00404
00408 unsigned rows_on_left_process = 0;
00409 std::vector<int> node_distr_on_left_process;
00410
00411 unsigned num_local_rows = localDistribution.size();
00412
00413 MPI_Send(&num_local_rows, 1, MPI_UNSIGNED, proc_right, 123, PETSC_COMM_WORLD);
00414 MPI_Recv(&rows_on_left_process, 1, MPI_UNSIGNED, proc_left, 123, PETSC_COMM_WORLD, &status);
00415
00416 node_distr_on_left_process.resize(rows_on_left_process > 0 ? rows_on_left_process : 1);
00417
00418 MPI_Send(&localDistribution[0], num_local_rows, MPI_INT, proc_right, 123, PETSC_COMM_WORLD);
00419 MPI_Recv(&node_distr_on_left_process[0], rows_on_left_process, MPI_INT, proc_left, 123, PETSC_COMM_WORLD, &status);
00420
00424 int local_load = 0;
00425 for (unsigned i=0; i<localDistribution.size(); i++)
00426 {
00427 local_load += localDistribution[i];
00428 }
00429 int load_on_left_proc = 0;
00430 for (unsigned i=0; i<node_distr_on_left_process.size(); i++)
00431 {
00432 load_on_left_proc += node_distr_on_left_process[i];
00433 }
00434
00435 if (!PetscTools::AmMaster())
00436 {
00437
00438
00439 int local_to_left_sq = (local_load - load_on_left_proc) * (local_load - load_on_left_proc);
00440 int delta_left = ( (local_load + node_distr_on_left_process[node_distr_on_left_process.size() - 1]) - (load_on_left_proc - node_distr_on_left_process[node_distr_on_left_process.size() - 1]) );
00441 delta_left = delta_left*delta_left - local_to_left_sq;
00442
00443 int delta_right = ( (local_load - localDistribution[0]) - (load_on_left_proc + localDistribution[0]));
00444 delta_right = delta_right*delta_right - local_to_left_sq;
00445
00446
00447 int local_change = 0;
00448 bool move_left = (!(delta_left > 0) && (node_distr_on_left_process.size() > 1));
00449 if (move_left)
00450 {
00451 local_change = 1;
00452 }
00453
00454 bool move_right = !(delta_right > 0) && (localDistribution.size() > 2);
00455 if (move_right)
00456 {
00457 local_change = -1;
00458 }
00459
00460 if (move_left && move_right)
00461 {
00462 local_change = (fabs((double)delta_right) > fabs((double)delta_left)) ? -1 : 1;
00463 }
00464
00465
00466 new_rows += local_change;
00467
00468
00469 MPI_Send(&local_change, 1, MPI_INT, proc_left, 123, PETSC_COMM_WORLD);
00470 }
00471
00472
00473 int remote_change = 0;
00474 MPI_Recv(&remote_change, 1, MPI_INT, proc_right, 123, PETSC_COMM_WORLD, &status);
00475
00476
00477 new_rows -= remote_change;
00478
00479 return new_rows;
00480 }
00481
00482 template<unsigned DIM>
00483 void DistributedBoxCollection<DIM>::SetupLocalBoxesHalfOnly()
00484 {
00485 if (mAreLocalBoxesSet)
00486 {
00487 EXCEPTION("Local Boxes Are Already Set");
00488 }
00489 else
00490 {
00491 switch (DIM)
00492 {
00493 case 1:
00494 {
00495
00496 mLocalBoxes.clear();
00497
00498
00499 for (unsigned global_index = mMinBoxIndex; global_index<mMaxBoxIndex+1; global_index++)
00500 {
00501 std::set<unsigned> local_boxes;
00502
00503
00504 local_boxes.insert(global_index);
00505
00506
00507 bool right = (global_index==mNumBoxesEachDirection(0)-1);
00508 bool left = (global_index == 0);
00509 bool proc_left = (global_index == mpDistributedBoxStackFactory->GetLow());
00510
00511
00512 if (!right)
00513 {
00514 local_boxes.insert(global_index+1);
00515 }
00516
00517 if (proc_left && !left)
00518 {
00519 local_boxes.insert(global_index-1);
00520 }
00521
00522 mLocalBoxes.push_back(local_boxes);
00523 }
00524 break;
00525 }
00526 case 2:
00527 {
00528
00529 mLocalBoxes.clear();
00530
00531 for (unsigned global_index = mMinBoxIndex; global_index<mMaxBoxIndex+1; global_index++)
00532 {
00533 std::set<unsigned> local_boxes;
00534
00535
00536 bool left = (global_index%mNumBoxesEachDirection(0) == 0);
00537 bool right = (global_index%mNumBoxesEachDirection(0) == mNumBoxesEachDirection(0)-1);
00538 bool top = !(global_index < mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1) - mNumBoxesEachDirection(0));
00539 bool bottom = (global_index < mNumBoxesEachDirection(0));
00540 bool bottom_proc = (CalculateCoordinateIndices(global_index)[1] == mpDistributedBoxStackFactory->GetLow());
00541
00542
00543 local_boxes.insert(global_index);
00544
00545
00546 if(!bottom && bottom_proc)
00547 {
00548 local_boxes.insert(global_index - mNumBoxesEachDirection(0));
00549 if(!left)
00550 {
00551 local_boxes.insert(global_index - mNumBoxesEachDirection(0) - 1);
00552 }
00553 if(!right)
00554 {
00555 local_boxes.insert(global_index - mNumBoxesEachDirection(0) + 1);
00556 }
00557 }
00558
00559
00560 if(!top)
00561 {
00562 local_boxes.insert(global_index + mNumBoxesEachDirection(0));
00563
00564 if(!right)
00565 {
00566 local_boxes.insert(global_index + mNumBoxesEachDirection(0) + 1);
00567 }
00568 if(!left)
00569 {
00570 local_boxes.insert(global_index + mNumBoxesEachDirection(0) - 1);
00571 }
00572 else if ( (global_index % mNumBoxesEachDirection(0) == 0) && (mIsPeriodicInX) )
00573 {
00574 local_boxes.insert(global_index + 2 * mNumBoxesEachDirection(0) - 1);
00575 }
00576 }
00577
00578
00579 if(!right)
00580 {
00581 local_boxes.insert(global_index + 1);
00582 }
00583
00584 else if ( (global_index % mNumBoxesEachDirection(0) == mNumBoxesEachDirection(0)-1) && (mIsPeriodicInX) )
00585 {
00586 local_boxes.insert(global_index - mNumBoxesEachDirection(0) + 1);
00587
00588 if (global_index < mBoxes.size() - mNumBoxesEachDirection(0))
00589 {
00590 local_boxes.insert(global_index + 1);
00591 }
00592 }
00593
00594 mLocalBoxes.push_back(local_boxes);
00595 }
00596 break;
00597 }
00598 case 3:
00599 {
00600
00601 mLocalBoxes.clear();
00602 unsigned num_boxes_xy = mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1);
00603
00604
00605 for (unsigned global_index = mMinBoxIndex; global_index<mMaxBoxIndex+1; global_index++)
00606 {
00607 std::set<unsigned> local_boxes;
00608
00609
00610 bool top = !(global_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0));
00611 bool bottom = (global_index % num_boxes_xy < mNumBoxesEachDirection(0));
00612 bool left = (global_index % mNumBoxesEachDirection(0) == 0);
00613 bool right = (global_index % mNumBoxesEachDirection(0) == mNumBoxesEachDirection(0) - 1);
00614 bool front = (global_index < num_boxes_xy);
00615 bool back = !(global_index < num_boxes_xy*mNumBoxesEachDirection(2) - num_boxes_xy);
00616 bool proc_front = (CalculateCoordinateIndices(global_index)[2] == mpDistributedBoxStackFactory->GetLow());
00617 bool proc_back = (CalculateCoordinateIndices(global_index)[2] == mpDistributedBoxStackFactory->GetHigh()-1);
00618
00619
00620 local_boxes.insert(global_index);
00621
00622
00623 if(!front)
00624 {
00625
00626 if(!top)
00627 {
00628 local_boxes.insert( global_index - num_boxes_xy + mNumBoxesEachDirection(0) );
00629 if(!left)
00630 {
00631 local_boxes.insert( global_index - num_boxes_xy + mNumBoxesEachDirection(0) - 1);
00632 }
00633 if(!right)
00634 {
00635 local_boxes.insert( global_index - num_boxes_xy + mNumBoxesEachDirection(0) + 1);
00636 }
00637 }
00638 if(!right)
00639 {
00640 local_boxes.insert( global_index - num_boxes_xy + 1);
00641 }
00642
00643
00644 if(proc_front)
00645 {
00646 local_boxes.insert( global_index - num_boxes_xy );
00647
00648 if(!left)
00649 {
00650 local_boxes.insert( global_index - num_boxes_xy - 1);
00651 }
00652 if(!bottom)
00653 {
00654 local_boxes.insert( global_index - num_boxes_xy - mNumBoxesEachDirection(0));
00655
00656 if(!left)
00657 {
00658 local_boxes.insert( global_index - num_boxes_xy - mNumBoxesEachDirection(0) - 1);
00659 }
00660 if(!right)
00661 {
00662 local_boxes.insert( global_index - num_boxes_xy - mNumBoxesEachDirection(0) + 1);
00663 }
00664 }
00665
00666 }
00667 }
00668 if(!right)
00669 {
00670 local_boxes.insert( global_index + 1);
00671 }
00672
00673 if(!top)
00674 {
00675 local_boxes.insert( global_index + mNumBoxesEachDirection(0));
00676
00677 if(!right)
00678 {
00679 local_boxes.insert( global_index + mNumBoxesEachDirection(0) + 1);
00680 }
00681 if(!left)
00682 {
00683 local_boxes.insert( global_index + mNumBoxesEachDirection(0) - 1);
00684 }
00685 }
00686
00687
00688 if(!back)
00689 {
00690 local_boxes.insert(global_index + num_boxes_xy);
00691
00692 if(!right)
00693 {
00694 local_boxes.insert(global_index + num_boxes_xy + 1);
00695 }
00696 if(!top)
00697 {
00698 local_boxes.insert(global_index + num_boxes_xy + mNumBoxesEachDirection(0));
00699 if(!right)
00700 {
00701 local_boxes.insert(global_index + num_boxes_xy + mNumBoxesEachDirection(0) + 1);
00702 }
00703 if(!left)
00704 {
00705 local_boxes.insert(global_index + num_boxes_xy + mNumBoxesEachDirection(0) - 1);
00706 }
00707 }
00708
00709 if(proc_back)
00710 {
00711 if(!left)
00712 {
00713 local_boxes.insert(global_index + num_boxes_xy - 1);
00714 }
00715 if(!bottom)
00716 {
00717 local_boxes.insert(global_index + num_boxes_xy - mNumBoxesEachDirection(0));
00718
00719 if(!left)
00720 {
00721 local_boxes.insert(global_index + num_boxes_xy - mNumBoxesEachDirection(0) - 1);
00722 }
00723 if(!right)
00724 {
00725 local_boxes.insert(global_index + num_boxes_xy - mNumBoxesEachDirection(0) + 1);
00726 }
00727 }
00728 }
00729 }
00730 mLocalBoxes.push_back(local_boxes);
00731 }
00732
00733 break;
00734 }
00735 default:
00736 NEVER_REACHED;
00737 }
00738 mAreLocalBoxesSet=true;
00739 }
00740 }
00741
00742
00743
00744 template<unsigned DIM>
00745 void DistributedBoxCollection<DIM>::SetupAllLocalBoxes()
00746 {
00747 mAreLocalBoxesSet = true;
00748 switch (DIM)
00749 {
00750 case 1:
00751 {
00752 for (unsigned i=mMinBoxIndex; i<mMaxBoxIndex+1; i++)
00753 {
00754 std::set<unsigned> local_boxes;
00755
00756 local_boxes.insert(i);
00757
00758
00759 if (i!=0)
00760 {
00761 local_boxes.insert(i-1);
00762 }
00763 if (i+1 != mNumBoxesEachDirection(0))
00764 {
00765 local_boxes.insert(i+1);
00766 }
00767
00768 mLocalBoxes.push_back(local_boxes);
00769 }
00770 break;
00771 }
00772 case 2:
00773 {
00774 mLocalBoxes.clear();
00775
00776 unsigned M = mNumBoxesEachDirection(0);
00777 unsigned N = mNumBoxesEachDirection(1);
00778
00779 std::vector<bool> is_xmin(N*M);
00780 std::vector<bool> is_xmax(N*M);
00781 std::vector<bool> is_ymin(N*M);
00782 std::vector<bool> is_ymax(N*M);
00783
00784 for (unsigned i=0; i<M*N; i++)
00785 {
00786 is_xmin[i] = (i%M==0);
00787 is_xmax[i] = ((i+1)%M==0);
00788 is_ymin[i] = (i%(M*N)<M);
00789 is_ymax[i] = (i%(M*N)>=(N-1)*M);
00790 }
00791
00792 for (unsigned i=mMinBoxIndex; i<mMaxBoxIndex+1; i++)
00793 {
00794 std::set<unsigned> local_boxes;
00795
00796 local_boxes.insert(i);
00797
00798
00799 if (!is_xmin[i])
00800 {
00801 local_boxes.insert(i-1);
00802 }
00803 else
00804 {
00805 if(mIsPeriodicInX)
00806 {
00807 local_boxes.insert(i+M-1);
00808 }
00809 }
00810
00811
00812 if (!is_xmax[i])
00813 {
00814 local_boxes.insert(i+1);
00815 }
00816 else
00817 {
00818 if(mIsPeriodicInX)
00819 {
00820 local_boxes.insert(i-M+1);
00821 }
00822 }
00823
00824
00825 if (!is_ymin[i])
00826 {
00827 local_boxes.insert(i-M);
00828 }
00829
00830
00831 if (!is_ymax[i])
00832 {
00833 local_boxes.insert(i+M);
00834 }
00835
00836
00837
00838 if ( (!is_xmin[i]) && (!is_ymin[i]) )
00839 {
00840 local_boxes.insert(i-1-M);
00841 }
00842 if ( (!is_xmin[i]) && (!is_ymax[i]) )
00843 {
00844 local_boxes.insert(i-1+M);
00845 }
00846 if ( (!is_xmax[i]) && (!is_ymin[i]) )
00847 {
00848 local_boxes.insert(i+1-M);
00849 }
00850 if ( (!is_xmax[i]) && (!is_ymax[i]) )
00851 {
00852 local_boxes.insert(i+1+M);
00853 }
00854
00855
00856 if(mIsPeriodicInX)
00857 {
00858 if( (is_xmin[i]) && (!is_ymin[i]) )
00859 {
00860 local_boxes.insert(i-1);
00861 }
00862 if ( (is_xmin[i]) && (!is_ymax[i]) )
00863 {
00864 local_boxes.insert(i-1+2*M);
00865 }
00866 if ( (is_xmax[i]) && (!is_ymin[i]) )
00867 {
00868 local_boxes.insert(i+1-2*M);
00869 }
00870 if ( (is_xmax[i]) && (!is_ymax[i]) )
00871 {
00872 local_boxes.insert(i+1);
00873 }
00874 }
00875
00876 mLocalBoxes.push_back(local_boxes);
00877 }
00878 break;
00879 }
00880 case 3:
00881 {
00882 mLocalBoxes.clear();
00883
00884 unsigned M = mNumBoxesEachDirection(0);
00885 unsigned N = mNumBoxesEachDirection(1);
00886 unsigned P = mNumBoxesEachDirection(2);
00887
00888 std::vector<bool> is_xmin(N*M*P);
00889 std::vector<bool> is_xmax(N*M*P);
00890 std::vector<bool> is_ymin(N*M*P);
00891 std::vector<bool> is_ymax(N*M*P);
00892 std::vector<bool> is_zmin(N*M*P);
00893 std::vector<bool> is_zmax(N*M*P);
00894
00895 for (unsigned i=0; i<M*N*P; i++)
00896 {
00897 is_xmin[i] = (i%M==0);
00898 is_xmax[i] = ((i+1)%M==0);
00899 is_ymin[i] = (i%(M*N)<M);
00900 is_ymax[i] = (i%(M*N)>=(N-1)*M);
00901 is_zmin[i] = (i<M*N);
00902 is_zmax[i] = (i>=M*N*(P-1));
00903 }
00904
00905 for (unsigned i=mMinBoxIndex; i<mMaxBoxIndex+1; i++)
00906 {
00907 std::set<unsigned> local_boxes;
00908
00909
00910 local_boxes.insert(i);
00911
00912
00913
00914
00915 if (!is_xmin[i])
00916 {
00917 local_boxes.insert(i-1);
00918
00919
00920 if (!is_ymin[i])
00921 {
00922 local_boxes.insert(i-1-M);
00923 }
00924
00925 if (!is_ymax[i])
00926 {
00927 local_boxes.insert(i-1+M);
00928 }
00929
00930 if (!is_zmin[i])
00931 {
00932 local_boxes.insert(i-1-M*N);
00933 }
00934
00935 if (!is_zmax[i])
00936 {
00937 local_boxes.insert(i-1+M*N);
00938 }
00939 }
00940
00941
00942 if (!is_xmax[i])
00943 {
00944 local_boxes.insert(i+1);
00945
00946
00947 if (!is_ymin[i])
00948 {
00949 local_boxes.insert(i+1-M);
00950 }
00951
00952 if (!is_ymax[i])
00953 {
00954 local_boxes.insert(i+1+M);
00955 }
00956
00957 if (!is_zmin[i])
00958 {
00959 local_boxes.insert(i+1-M*N);
00960 }
00961
00962 if (!is_zmax[i])
00963 {
00964 local_boxes.insert(i+1+M*N);
00965 }
00966 }
00967
00968
00969 if (!is_ymin[i])
00970 {
00971 local_boxes.insert(i-M);
00972
00973
00974 if (!is_zmin[i])
00975 {
00976 local_boxes.insert(i-M-M*N);
00977 }
00978
00979 if (!is_zmax[i])
00980 {
00981 local_boxes.insert(i-M+M*N);
00982 }
00983 }
00984
00985
00986 if (!is_ymax[i])
00987 {
00988 local_boxes.insert(i+M);
00989
00990
00991 if (!is_zmin[i])
00992 {
00993 local_boxes.insert(i+M-M*N);
00994 }
00995
00996 if (!is_zmax[i])
00997 {
00998 local_boxes.insert(i+M+M*N);
00999 }
01000 }
01001
01002
01003 if (!is_zmin[i])
01004 {
01005 local_boxes.insert(i-N*M);
01006 }
01007
01008
01009 if (!is_zmax[i])
01010 {
01011 local_boxes.insert(i+N*M);
01012 }
01013
01014
01015
01016 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmin[i]) )
01017 {
01018 local_boxes.insert(i-1-M-M*N);
01019 }
01020
01021 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmax[i]) )
01022 {
01023 local_boxes.insert(i-1-M+M*N);
01024 }
01025
01026 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmin[i]) )
01027 {
01028 local_boxes.insert(i-1+M-M*N);
01029 }
01030
01031 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmax[i]) )
01032 {
01033 local_boxes.insert(i-1+M+M*N);
01034 }
01035
01036 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmin[i]) )
01037 {
01038 local_boxes.insert(i+1-M-M*N);
01039 }
01040
01041 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmax[i]) )
01042 {
01043 local_boxes.insert(i+1-M+M*N);
01044 }
01045
01046 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmin[i]) )
01047 {
01048 local_boxes.insert(i+1+M-M*N);
01049 }
01050
01051 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmax[i]) )
01052 {
01053 local_boxes.insert(i+1+M+M*N);
01054 }
01055
01056 mLocalBoxes.push_back(local_boxes);
01057 }
01058 break;
01059 }
01060 default:
01061 NEVER_REACHED;
01062 }
01063 }
01064
01065 template<unsigned DIM>
01066 std::set<unsigned> DistributedBoxCollection<DIM>::GetLocalBoxes(unsigned boxIndex)
01067 {
01068
01069 assert(!(boxIndex < mMinBoxIndex) && !(mMaxBoxIndex<boxIndex));
01070 return mLocalBoxes[boxIndex-mMinBoxIndex];
01071 }
01072
01073 template<unsigned DIM>
01074 bool DistributedBoxCollection<DIM>::IsOwned(Node<DIM>* pNode)
01075 {
01076 unsigned index = CalculateContainingBox(pNode);
01077
01078 return GetBoxOwnership(index);
01079 }
01080
01081 template<unsigned DIM>
01082 bool DistributedBoxCollection<DIM>::IsOwned(c_vector<double, DIM>& location)
01083 {
01084 unsigned index = CalculateContainingBox(location);
01085
01086 return GetBoxOwnership(index);
01087 }
01088
01089 template<unsigned DIM>
01090 unsigned DistributedBoxCollection<DIM>::GetProcessOwningNode(Node<DIM>* pNode)
01091 {
01092 unsigned box_index = CalculateContainingBox(pNode);
01093 unsigned containing_process = PetscTools::GetMyRank();
01094
01095 if (box_index > mMaxBoxIndex)
01096 {
01097 containing_process++;
01098 }
01099 else if (box_index < mMinBoxIndex)
01100 {
01101 containing_process--;
01102 }
01103
01104 return containing_process;
01105 }
01106
01107 template<unsigned DIM>
01108 std::vector<unsigned>& DistributedBoxCollection<DIM>::rGetHaloNodesRight()
01109 {
01110 return mHaloNodesRight;
01111 }
01112
01113 template<unsigned DIM>
01114 std::vector<unsigned>& DistributedBoxCollection<DIM>::rGetHaloNodesLeft()
01115 {
01116 return mHaloNodesLeft;
01117 }
01118
01119 template<unsigned DIM>
01120 void DistributedBoxCollection<DIM>::SetCalculateNodeNeighbours(bool calculateNodeNeighbours)
01121 {
01122 mCalculateNodeNeighbours = calculateNodeNeighbours;
01123 }
01124
01125 template<unsigned DIM>
01126 void DistributedBoxCollection<DIM>::CalculateNodePairs(std::vector<Node<DIM>*>& rNodes, std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
01127 {
01128 rNodePairs.clear();
01129 rNodeNeighbours.clear();
01130
01131
01132 for (unsigned i=0; i<rNodes.size(); i++)
01133 {
01134 unsigned node_index = rNodes[i]->GetIndex();
01135
01136
01137 unsigned box_index = CalculateContainingBox(rNodes[i]);
01138
01139 if (GetBoxOwnership(box_index))
01140 {
01141 rNodeNeighbours[node_index] = std::set<unsigned>();
01142 }
01143 }
01144
01145 for (std::map<unsigned, unsigned>::iterator map_iter = mBoxesMapping.begin();
01146 map_iter != mBoxesMapping.end();
01147 ++map_iter)
01148 {
01149
01150 unsigned box_index = map_iter->first;
01151
01152 AddPairsFromBox(box_index, rNodePairs, rNodeNeighbours);
01153 }
01154 }
01155
01156 template<unsigned DIM>
01157 void DistributedBoxCollection<DIM>::CalculateInteriorNodePairs(std::vector<Node<DIM>*>& rNodes, std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
01158 {
01159 rNodePairs.clear();
01160 rNodeNeighbours.clear();
01161
01162
01163 for (unsigned i=0; i<rNodes.size(); i++)
01164 {
01165 unsigned node_index = rNodes[i]->GetIndex();
01166
01167
01168 unsigned box_index = CalculateContainingBox(rNodes[i]);
01169
01170 if (GetBoxOwnership(box_index))
01171 {
01172 rNodeNeighbours[node_index] = std::set<unsigned>();
01173 }
01174 }
01175
01176 for (std::map<unsigned, unsigned>::iterator map_iter = mBoxesMapping.begin();
01177 map_iter != mBoxesMapping.end();
01178 ++map_iter)
01179 {
01180
01181 unsigned box_index = map_iter->first;
01182
01183 if (IsInteriorBox(box_index))
01184 {
01185 AddPairsFromBox(box_index, rNodePairs, rNodeNeighbours);
01186 }
01187 }
01188 }
01189
01190 template<unsigned DIM>
01191 void DistributedBoxCollection<DIM>::CalculateBoundaryNodePairs(std::vector<Node<DIM>*>& rNodes, std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
01192 {
01193 for (std::map<unsigned, unsigned>::iterator map_iter = mBoxesMapping.begin();
01194 map_iter != mBoxesMapping.end();
01195 ++map_iter)
01196 {
01197
01198 unsigned box_index = map_iter->first;
01199
01200 if (!IsInteriorBox(box_index))
01201 {
01202 AddPairsFromBox(box_index, rNodePairs, rNodeNeighbours);
01203 }
01204 }
01205 }
01206
01207 template<unsigned DIM>
01208 void DistributedBoxCollection<DIM>::AddPairsFromBox(unsigned boxIndex, std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
01209 {
01210
01211 Box<DIM> box = rGetBox(boxIndex);
01212
01213
01214 std::set< Node<DIM>* >& r_contained_nodes = box.rGetNodesContained();
01215
01216
01217 std::set<unsigned> local_boxes_indices = GetLocalBoxes(boxIndex);
01218
01219
01220 for (std::set<unsigned>::iterator box_iter = local_boxes_indices.begin();
01221 box_iter != local_boxes_indices.end();
01222 box_iter++)
01223 {
01224 Box<DIM>* p_neighbour_box;
01225
01226
01227 if (GetBoxOwnership(*box_iter))
01228 {
01229 p_neighbour_box = &mBoxes[mBoxesMapping[*box_iter]];
01230 }
01231 else
01232 {
01233 p_neighbour_box = &mHaloBoxes[mHaloBoxesMapping[*box_iter]];
01234 }
01235 assert(p_neighbour_box);
01236
01237
01238 std::set< Node<DIM>* >& r_contained_neighbour_nodes = p_neighbour_box->rGetNodesContained();
01239
01240
01241 for (typename std::set<Node<DIM>*>::iterator neighbour_node_iter = r_contained_neighbour_nodes.begin();
01242 neighbour_node_iter != r_contained_neighbour_nodes.end();
01243 ++neighbour_node_iter)
01244 {
01245
01246 unsigned other_node_index = (*neighbour_node_iter)->GetIndex();
01247
01248
01249 for (typename std::set<Node<DIM>*>::iterator node_iter = r_contained_nodes.begin();
01250 node_iter != r_contained_nodes.end();
01251 ++node_iter)
01252 {
01253 unsigned node_index = (*node_iter)->GetIndex();
01254
01255
01256 if (*box_iter == boxIndex)
01257 {
01258 if (other_node_index > node_index)
01259 {
01260 rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>((*node_iter), (*neighbour_node_iter)));
01261 if (mCalculateNodeNeighbours)
01262 {
01263 rNodeNeighbours[node_index].insert(other_node_index);
01264 rNodeNeighbours[other_node_index].insert(node_index);
01265 }
01266 }
01267 }
01268 else
01269 {
01270 rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>((*node_iter), (*neighbour_node_iter)));
01271 if (mCalculateNodeNeighbours)
01272 {
01273 rNodeNeighbours[node_index].insert(other_node_index);
01274 rNodeNeighbours[other_node_index].insert(node_index);
01275 }
01276 }
01277
01278 }
01279 }
01280 }
01281 }
01282
01283 template<unsigned DIM>
01284 std::vector<int> DistributedBoxCollection<DIM>::CalculateNumberOfNodesInEachStrip()
01285 {
01286 std::vector<int> cell_numbers(mpDistributedBoxStackFactory->GetHigh() - mpDistributedBoxStackFactory->GetLow(), 0);
01287
01288 for (std::map<unsigned, unsigned>::iterator iter = mBoxesMapping.begin();
01289 iter != mBoxesMapping.end();
01290 ++iter)
01291 {
01292 c_vector<unsigned, DIM> coords = CalculateCoordinateIndices(iter->first);
01293 unsigned location_in_vector = coords[DIM-1]-mpDistributedBoxStackFactory->GetLow();
01294
01295 cell_numbers[location_in_vector] += mBoxes[iter->second].rGetNodesContained().size();
01296 }
01297
01298 return cell_numbers;
01299 }
01300
01302
01304
01305 template class DistributedBoxCollection<1>;
01306 template class DistributedBoxCollection<2>;
01307 template class DistributedBoxCollection<3>;