DistributedBoxCollection.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2014, 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 "DistributedBoxCollection.hpp"
00036 #include "Exception.hpp"
00037 #include "MathsCustomFunctions.hpp"
00038 
00039 // Static member for "fudge factor" is instantiated here
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     // Periodicity only works in 2d and in serial.
00051     if (isPeriodicInX)
00052     {
00053         assert(DIM==2 && PetscTools::IsSequential());
00054     }
00055 
00056     // If the domain size is not 'divisible' (i.e. fmod(width, box_size) > 0.0) we swell the domain to enforce this.
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     // Calculate the number of boxes in each direction.
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     // Make sure there are enough boxes for the number of processes.
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     // Make a distributed vectory factory to split the rows of boxes between processes.
00089     mpDistributedBoxStackFactory = new DistributedVectorFactory(mNumBoxesEachDirection(DIM-1), localRows);
00090 
00091     // Calculate how many boxes in a row / face. A useful piece of data in the class.
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      * The location of the Boxes doesn't matter as it isn't actually used so we don't bother to work it out.
00105      * The reason it isn't used is because this class works out which box a node lies in without refernece to actual
00106      * box locations, only their global index within the collection.
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     // Get top-most and bottom-most value of Distributed Box Stack.
00144     unsigned Hi = mpDistributedBoxStackFactory->GetHigh();
00145     unsigned Lo = mpDistributedBoxStackFactory->GetLow();
00146 
00147     // If I am not the top-most process, add halo structures to the right.
00148     if (!PetscTools::AmTopMost())
00149     {
00150         for (unsigned i=0; i < mNumBoxesInAFace; i++)
00151         {
00152             c_vector<double, 2*DIM> arbitrary_location; // See comment in constructor.
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     // If I am not the bottom-most process, add halo structures to the left.
00163     if (!PetscTools::AmMaster())
00164     {
00165         for (unsigned i=0; i< mNumBoxesInAFace; i++)
00166         {
00167             c_vector<double, 2*DIM> arbitrary_location; // See comment in constructor.
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     // Send right
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     // Get the location of the node
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     // The node must lie inside the boundary of the box collection
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     // Compute the containing box index in each dimension
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     // Use these to compute the index of the containing box
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     // This index must be less than the total number of boxes
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     // A variable that will return the new number of rows.
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         // Calculate (Difference in load with a shift) - (Difference in current loads) for a move left and right of the boundary
00438         // This code uses integer arithmetic in order to avoid the rounding errors associated with doubles
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         // If a delta is negative we should accept that change. If both are negative choose the largest change.
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         // Update the number of local rows.
00466         new_rows += local_change;
00467 
00468         // Send the result of the calculation back to the left processes.
00469         MPI_Send(&local_change, 1, MPI_INT, proc_left, 123, PETSC_COMM_WORLD);
00470     }
00471 
00472     // Receive changes from right hand process.
00473     int remote_change = 0;
00474     MPI_Recv(&remote_change, 1, MPI_INT, proc_right, 123, PETSC_COMM_WORLD, &status);
00475 
00476     // Update based on change or right/top boundary
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                 // We only need to look for neighbours in the current and successive boxes plus some others for halos
00496                 mLocalBoxes.clear();
00497 
00498                 // Iterate over the global box indices
00499                 for (unsigned global_index = mMinBoxIndex; global_index<mMaxBoxIndex+1; global_index++)
00500                 {
00501                     std::set<unsigned> local_boxes;
00502 
00503                     // Insert the current box
00504                     local_boxes.insert(global_index);
00505 
00506                     // Set some bools to find out where we are
00507                     bool right = (global_index==mNumBoxesEachDirection(0)-1);
00508                     bool left = (global_index == 0);
00509                     bool proc_left = (global_index == mpDistributedBoxStackFactory->GetLow());
00510 
00511                     // If we're not at the right-most box, then insert the box to the right
00512                     if (!right)
00513                     {
00514                         local_boxes.insert(global_index+1);
00515                     }
00516                     // If we're on a left process boundary and not on process 0, insert the (halo) box to the left
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                 // We only need to look for neighbours in the current box and half the neighbouring boxes plus some others for halos
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                     // Set up bools to find out where we are
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                     // Insert the current box
00543                     local_boxes.insert(global_index);
00544 
00545                     // If we're on the bottom of the process boundary, but not the bottom of the domain add boxes below
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                     // If we're not at the top of the domain insert boxes above
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) ) // If we're on the left edge but its periodic include the box on the far right and up one.
00573                         {
00574                             local_boxes.insert(global_index +  2 * mNumBoxesEachDirection(0) - 1);
00575                         }
00576                     }
00577 
00578                     // If we're not on the far right hand side inseryt box to the right
00579                     if(!right)
00580                     {
00581                         local_boxes.insert(global_index + 1);
00582                     }
00583                     // If we're on the right edge but it's periodic include the box on the far left of the domain
00584                     else if ( (global_index % mNumBoxesEachDirection(0) == mNumBoxesEachDirection(0)-1) && (mIsPeriodicInX) )
00585                     {
00586                         local_boxes.insert(global_index - mNumBoxesEachDirection(0) + 1);
00587                         // If we're also not on the top-most row, then insert the box above- on the far left of the domain
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                 // We only need to look for neighbours in the current box and half the neighbouring boxes plus some others for halos
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                     // Set some bools to find out where we are
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                     // Insert the current box
00620                     local_boxes.insert(global_index);
00621 
00622                     // If we're not on the front face, add appropriate boxes on the closer face
00623                     if(!front)
00624                     {
00625                         // If we're not on the top of the domain
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                         // If we are on the front of the process we have to add extra boxes as they are halos.
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                     // If we're not on the very top add boxes above
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                     // If we're not on the back add boxes behind
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                         // If we are on the back proc we should make sure we get everything in the face further back
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                 // add the two neighbours
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); // far left
00780             std::vector<bool> is_xmax(N*M); // far right
00781             std::vector<bool> is_ymin(N*M); // bottom
00782             std::vector<bool> is_ymax(N*M); // top
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                 // add the box to the left
00799                 if (!is_xmin[i])
00800                 {
00801                     local_boxes.insert(i-1);
00802                 }
00803                 else // Add Periodic Box if needed
00804                 {
00805                     if(mIsPeriodicInX)
00806                     {
00807                         local_boxes.insert(i+M-1);
00808                     }
00809                 }
00810 
00811                 // add the box to the right
00812                 if (!is_xmax[i])
00813                 {
00814                     local_boxes.insert(i+1);
00815                 }
00816                 else // Add Periodic Box if needed
00817                 {
00818                     if(mIsPeriodicInX)
00819                     {
00820                         local_boxes.insert(i-M+1);
00821                     }
00822                 }
00823 
00824                 // add the one below
00825                 if (!is_ymin[i])
00826                 {
00827                     local_boxes.insert(i-M);
00828                 }
00829 
00830                 // add the one above
00831                 if (!is_ymax[i])
00832                 {
00833                     local_boxes.insert(i+M);
00834                 }
00835 
00836                 // add the four corner boxes
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                 // Add Periodic Corner Boxes if needed
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); // far left
00889             std::vector<bool> is_xmax(N*M*P); // far right
00890             std::vector<bool> is_ymin(N*M*P); // nearest
00891             std::vector<bool> is_ymax(N*M*P); // furthest
00892             std::vector<bool> is_zmin(N*M*P); // bottom layer
00893             std::vector<bool> is_zmax(N*M*P); // top layer
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                 // add itself as a local box
00910                 local_boxes.insert(i);
00911 
00912                 // now add all 26 other neighbours.....
00913 
00914                 // add the box left
00915                 if (!is_xmin[i])
00916                 {
00917                     local_boxes.insert(i-1);
00918 
00919                     // plus some others towards the left
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                 // add the box to the right
00942                 if (!is_xmax[i])
00943                 {
00944                     local_boxes.insert(i+1);
00945 
00946                     // plus some others towards the right
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                 // add the boxes next along the y axis
00969                 if (!is_ymin[i])
00970                 {
00971                     local_boxes.insert(i-M);
00972 
00973                     // and more in this plane
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                 // add the boxes next along the y axis
00986                 if (!is_ymax[i])
00987                 {
00988                     local_boxes.insert(i+M);
00989 
00990                     // and more in this plane
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                 // add the box directly above
01003                 if (!is_zmin[i])
01004                 {
01005                     local_boxes.insert(i-N*M);
01006                 }
01007 
01008                 // add the box directly below
01009                 if (!is_zmax[i])
01010                 {
01011                     local_boxes.insert(i+N*M);
01012                 }
01013 
01014                 // finally, the 8 corners are left
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     // Make sure the box is locally owned
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     // Create an empty neighbours set for each node
01132     for (unsigned i=0; i<rNodes.size(); i++)
01133     {
01134         unsigned node_index = rNodes[i]->GetIndex();
01135 
01136         // Get the box containing this node
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         // Get the box global index
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     // Create an empty neighbours set for each node
01163     for (unsigned i=0; i<rNodes.size(); i++)
01164     {
01165         unsigned node_index = rNodes[i]->GetIndex();
01166 
01167         // Get the box containing this node
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         // Get the box global index
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         // Get the box global index
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     // Get the box
01211     Box<DIM> box = rGetBox(boxIndex);
01212 
01213     // Get the set of nodes in this box
01214     std::set< Node<DIM>* >& r_contained_nodes = box.rGetNodesContained();
01215 
01216     // Get the local boxes to this box
01217     std::set<unsigned> local_boxes_indices = GetLocalBoxes(boxIndex);
01218 
01219     // Loop over all the local boxes
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         // Establish whether box is locally owned or halo.
01227         if (GetBoxOwnership(*box_iter))
01228         {
01229             p_neighbour_box = &mBoxes[mBoxesMapping[*box_iter]];
01230         }
01231         else // Assume it is a halo.
01232         {
01233             p_neighbour_box = &mHaloBoxes[mHaloBoxesMapping[*box_iter]];
01234         }
01235         assert(p_neighbour_box);
01236 
01237         // Get the set of nodes contained in this box
01238         std::set< Node<DIM>* >& r_contained_neighbour_nodes = p_neighbour_box->rGetNodesContained();
01239 
01240         // Loop over these nodes
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             // Get the index of the other node
01246             unsigned other_node_index = (*neighbour_node_iter)->GetIndex();
01247 
01248             // Loop over nodes in this box
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                 // If we're in the same box, then take care not to store the node pair twice
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 // Explicit instantiation
01304 
01305 template class DistributedBoxCollection<1>;
01306 template class DistributedBoxCollection<2>;
01307 template class DistributedBoxCollection<3>;

Generated by  doxygen 1.6.2