DistributedBoxCollection.cpp

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

Generated by  doxygen 1.6.2