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