BoxCollection.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 "BoxCollection.hpp"
00036 #include "Exception.hpp"
00037 
00039 // BoxCollection methods
00041 
00042 // Static member for "fudge factor" is instantiated here
00043 template<unsigned DIM>
00044 const double BoxCollection<DIM>::msFudge = 5e-14;
00045 
00046 template<unsigned DIM>
00047 BoxCollection<DIM>::BoxCollection(double boxWidth, c_vector<double, 2*DIM> domainSize, bool isPeriodicInX)
00048     : mDomainSize(domainSize),
00049       mBoxWidth(boxWidth),
00050       mIsPeriodicInX(isPeriodicInX)
00051 {
00052     // Periodicity only works in 2d
00053     if (isPeriodicInX)
00054     {
00055         assert(DIM==2);
00056     }
00057 
00058     /*
00059      * Start by calculating the number of boxes in each direction and total number of boxes.
00060      * Also create a helper vector of coefficients, whose first entry is 1 and whose i-th
00061      * entry (for i>1) is the i-th partial product of the vector mNumBoxesEachDirection. This
00062      * vector of coefficients will be used in the next code block to compute how many boxes
00063      * along in each dimension each box, given its index.
00064      */
00065     unsigned num_boxes = 1;
00066     std::vector<unsigned> coefficients;
00067     coefficients.push_back(1);
00068 
00069     for (unsigned i=0; i<DIM; i++)
00070     {
00071         mNumBoxesEachDirection(i) = (unsigned) floor((domainSize(2*i+1) - domainSize(2*i))/boxWidth + msFudge) + 1;
00072         num_boxes *= mNumBoxesEachDirection(i);
00073         coefficients.push_back(coefficients[i]*mNumBoxesEachDirection(i));
00074     }
00075 
00076     for (unsigned box_index=0; box_index<num_boxes; box_index++)
00077     {
00078         /*
00079          * The code block below computes how many boxes along in each dimension the
00080          * current box is and stores this information in the second, ..., (DIM+1)th
00081          * entries of the vector current_box_indices. The first entry of
00082          * current_box_indices is zero to ensure that the for loop works correctly.
00083          *
00084          * Our convention is that in 3D the index of each box, box_index, is related
00085          * to its indices (i,j,k) by
00086          *
00087          * box_index = i + mNumBoxesEachDirection(0)*j
00088          *               + mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1)*k,
00089          *
00090          * while in 2D, box_index is related to (i,j) by
00091          *
00092          * box_index = i + mNumBoxesEachDirection(0)*j
00093          *
00094          * and in 1D we simply have box_index = i.
00095          */
00096         c_vector<unsigned, DIM+1> current_box_indices;
00097         current_box_indices[0] = 0;
00098 
00099         for (unsigned i=0; i<DIM; i++)
00100         {
00101             unsigned temp = 0;
00102             for (unsigned j=1; j<i; j++)
00103             {
00104                 temp += coefficients[j]*current_box_indices[j-1];
00105             }
00106             current_box_indices[i+1] = (box_index%coefficients[i+1] - temp)/coefficients[i];
00107         }
00108 
00109         /*
00110          * We now use the information stores in current_box_indices to construct the
00111          * Box, which we add to mBoxes.
00112          */
00113         c_vector<double, 2*DIM> box_coords;
00114         for (unsigned l=0; l<DIM; l++)
00115         {
00116             box_coords(2*l) = domainSize(2*l) + current_box_indices(l+1)*boxWidth;
00117             box_coords(2*l+1) = domainSize(2*l) + (current_box_indices(l+1)+1)*boxWidth;
00118         }
00119 
00120         Box<DIM> new_box(box_coords);
00121         mBoxes.push_back(new_box);
00122     }
00123 
00124     // Check that we have the correct number of boxes
00125     assert(num_boxes == mBoxes.size());
00126 }
00127 
00128 template<unsigned DIM>
00129 void BoxCollection<DIM>::EmptyBoxes()
00130 {
00131     for (unsigned i=0; i<mBoxes.size(); i++)
00132     {
00133         mBoxes[i].ClearNodes();
00134     }
00135 }
00136 
00137 template<unsigned DIM>
00138 unsigned BoxCollection<DIM>::CalculateContainingBox(Node<DIM>* pNode)
00139 {
00140     // Get the location of the node
00141     c_vector<double, DIM> location = pNode->rGetLocation();
00142     return CalculateContainingBox(location);
00143 }
00144 
00145 
00146 template<unsigned DIM>
00147 unsigned BoxCollection<DIM>::CalculateContainingBox(c_vector<double, DIM>& rLocation)
00148 {
00149     // The node must lie inside the boundary of the box collection
00150     for (unsigned i=0; i<DIM; i++)
00151     {
00152         if ( (rLocation[i] < mDomainSize(2*i)) || (rLocation[i] > mDomainSize(2*i+1)) )
00153         {
00154             EXCEPTION("The point provided is outside all of the boxes");
00155         }
00156     }
00157 
00158     // Compute the containing box index in each dimension
00159     c_vector<unsigned, DIM> containing_box_indices;
00160     for (unsigned i=0; i<DIM; i++)
00161     {
00162         containing_box_indices[i] = (unsigned) floor((rLocation[i] - mDomainSize(2*i) + msFudge)/mBoxWidth);
00163     }
00164 
00165     // Use these to compute the index of the containing box
00166     unsigned containing_box_index = 0;
00167     for (unsigned i=0; i<DIM; i++)
00168     {
00169         unsigned temp = 1;
00170         for (unsigned j=0; j<i; j++)
00171         {
00172             temp *= mNumBoxesEachDirection(j);
00173         }
00174         containing_box_index += temp*containing_box_indices[i];
00175     }
00176 
00177     // This index must be less than the number of boxes
00178     assert(containing_box_index < mBoxes.size());
00179 
00180     return containing_box_index;
00181 }
00182 
00183 template<unsigned DIM>
00184 Box<DIM>& BoxCollection<DIM>::rGetBox(unsigned boxIndex)
00185 {
00186     assert(boxIndex < mBoxes.size());
00187     return mBoxes[boxIndex];
00188 }
00189 
00190 template<unsigned DIM>
00191 unsigned BoxCollection<DIM>::GetNumBoxes()
00192 {
00193     return mBoxes.size();
00194 }
00195 
00196 template<unsigned DIM>
00197 void BoxCollection<DIM>::SetupLocalBoxesHalfOnly()
00198 {
00199     switch (DIM)
00200     {
00201         case 1:
00202         {
00203             // We only need to look for neighbours in the current and successive boxes
00204             mLocalBoxes.clear();
00205             for (unsigned box_index=0; box_index<mBoxes.size(); box_index++)
00206             {
00207                 std::set<unsigned> local_boxes;
00208 
00209                 // Insert the current box
00210                 local_boxes.insert(box_index);
00211 
00212                 // If we're not at the right-most box, then insert the box to the right
00213                 if (box_index < mNumBoxesEachDirection(0)-1)
00214                 {
00215                     local_boxes.insert(box_index+1);
00216                 }
00217                 mLocalBoxes.push_back(local_boxes);
00218             }
00219             break;
00220         }
00221         case 2:
00222         {
00223             // We only need to look for neighbours in the current box and half the neighbouring boxes
00224             mLocalBoxes.clear();
00225             for (unsigned box_index=0; box_index<mBoxes.size(); box_index++)
00226             {
00227                 std::set<unsigned> local_boxes;
00228 
00229                 // Insert the current box
00230                 local_boxes.insert(box_index);
00231 
00232                 // If we're not on the top-most row, then insert the box above
00233                 if (box_index < mBoxes.size() - mNumBoxesEachDirection(0))
00234                 {
00235                     local_boxes.insert(box_index + mNumBoxesEachDirection(0));
00236 
00237                     // If we're also not on the left-most column, then insert the box above-left
00238                     if (box_index % mNumBoxesEachDirection(0) != 0)
00239                     {
00240                         local_boxes.insert(box_index + mNumBoxesEachDirection(0) - 1);
00241                     }
00242                     // If we're on the left edge but its periodic include the box on the far right
00243                     else if ( (box_index % mNumBoxesEachDirection(0) == 0) && (mIsPeriodicInX) )
00244                     {
00245                         local_boxes.insert(box_index + 2* mNumBoxesEachDirection(0) - 1);
00246                     }
00247 
00248                 }
00249                 // If we're not on the right-most column, then insert the box to the right
00250                 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00251                 {
00252                     local_boxes.insert(box_index + 1);
00253 
00254                     // If we're also not on the top-most row, then insert the box above-right
00255                     if (box_index < mBoxes.size() - mNumBoxesEachDirection(0))
00256                     {
00257                         local_boxes.insert(box_index + mNumBoxesEachDirection(0) + 1);
00258                     }
00259                 }
00260                 // If we're on the right edge but it's periodic include the box on the far left of the domain
00261                 else if ( (box_index % mNumBoxesEachDirection(0) == mNumBoxesEachDirection(0)-1) && (mIsPeriodicInX) )
00262                 {
00263                     local_boxes.insert(box_index - mNumBoxesEachDirection(0) + 1);
00264                     // If we're also not on the top-most row, then insert the box above- on the far left of the domain
00265                     if (box_index < mBoxes.size() - mNumBoxesEachDirection(0))
00266                     {
00267                         local_boxes.insert(box_index + 1);
00268                     }
00269                 }
00270 
00271                 mLocalBoxes.push_back(local_boxes);
00272             }
00273             break;
00274         }
00275         case 3:
00276         {
00277             // We only need to look for neighbours in the current box and half the neighbouring boxes
00278             mLocalBoxes.clear();
00279             unsigned num_boxes_xy = mNumBoxesEachDirection(0)*mNumBoxesEachDirection(1);
00280 
00281             for (unsigned box_index=0; box_index<mBoxes.size(); box_index++)
00282             {
00283                 std::set<unsigned> local_boxes;
00284 
00285                 // Insert the current box
00286                 local_boxes.insert(box_index);
00287 
00288                 // If we're not on the far face (y max), then insert the far box
00289                 if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00290                 {
00291                     local_boxes.insert(box_index + mNumBoxesEachDirection(0));
00292 
00293                     // If we're also not on the left face (x min), then insert the box to the left
00294                     if (box_index % mNumBoxesEachDirection(0) != 0)
00295                     {
00296                         local_boxes.insert(box_index + mNumBoxesEachDirection(0) - 1);
00297                     }
00298                 }
00299                 // If we're not on the right face (x max), then insert the box to the right
00300                 if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00301                 {
00302                     local_boxes.insert(box_index + 1);
00303 
00304                     // If we're also not on the far face (y max) row, then insert the box to the far-right
00305                     if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00306                     {
00307                         local_boxes.insert(box_index + mNumBoxesEachDirection(0) + 1);
00308                     }
00309                 }
00310                 // If we're not on the top face (z max), then insert the box above
00311                 if (box_index < mBoxes.size() - num_boxes_xy)
00312                 {
00313                     local_boxes.insert(box_index + num_boxes_xy);
00314 
00315                     // If we're also not on the far face (y max), then insert the above-far box
00316                     if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00317                     {
00318                         local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0));
00319 
00320                         // If we're also not on the left face (x min), then insert the box to the above-left
00321                         if (box_index % mNumBoxesEachDirection(0) != 0)
00322                         {
00323                             local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0) - 1);
00324                         }
00325                     }
00326                     // If we're also not on the right face (x max), then insert the box to the above-right
00327                     if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00328                     {
00329                         local_boxes.insert(box_index + num_boxes_xy + 1);
00330 
00331                         // If we're also not on the far face (y max) row, then insert the box to the above-far-right
00332                         if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00333                         {
00334                             local_boxes.insert(box_index + num_boxes_xy + mNumBoxesEachDirection(0) + 1);
00335                         }
00336                     }
00337                 }
00338                 // If we're not on the bottom face (z min), then DON'T insert the box above - this will lead to duplicate pairs.
00339                 if (box_index >= num_boxes_xy)
00340                 {
00341                     // If we're also not on the far face (y max), then insert the below-far box
00342                     if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00343                     {
00344                         local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0));
00345 
00346                         // If we're also not on the left face (x min), then insert the box to the below-left
00347                         if (box_index % mNumBoxesEachDirection(0) != 0)
00348                         {
00349                             local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0) - 1);
00350                         }
00351                     }
00352                     // If we're also not on the right face (x max), then insert the box to the below-right
00353                     if (box_index % mNumBoxesEachDirection(0) != mNumBoxesEachDirection(0)-1)
00354                     {
00355                         local_boxes.insert(box_index - num_boxes_xy + 1);
00356 
00357                         // If we're also not on the far face (y max) row, then insert the box to the below-far-right
00358                         if (box_index % num_boxes_xy < num_boxes_xy - mNumBoxesEachDirection(0))
00359                         {
00360                             local_boxes.insert(box_index - num_boxes_xy + mNumBoxesEachDirection(0) + 1);
00361                         }
00362                     }
00363                 }
00364                 mLocalBoxes.push_back(local_boxes);
00365             }
00366             break;
00367         }
00368         default:
00369             NEVER_REACHED;
00370     }
00371 }
00372 
00373 
00374 
00375 template<unsigned DIM>
00376 void BoxCollection<DIM>::SetupAllLocalBoxes()
00377 {
00378     switch (DIM)
00379     {
00380         case 1:
00381         {
00382             for (unsigned i=0; i<mBoxes.size(); i++)
00383             {
00384                 std::set<unsigned> local_boxes;
00385 
00386                 local_boxes.insert(i);
00387 
00388                 // add the two neighbours
00389                 if (i!=0)
00390                 {
00391                     local_boxes.insert(i-1);
00392                 }
00393                 if (i+1 != mNumBoxesEachDirection(0))
00394                 {
00395                     local_boxes.insert(i+1);
00396                 }
00397 
00398                 mLocalBoxes.push_back(local_boxes);
00399             }
00400             break;
00401         }
00402         case 2:
00403         {
00404             mLocalBoxes.clear();
00405 
00406             unsigned M = mNumBoxesEachDirection(0);
00407             unsigned N = mNumBoxesEachDirection(1);
00408 
00409             std::vector<bool> is_xmin(N*M); // far left
00410             std::vector<bool> is_xmax(N*M); // far right
00411             std::vector<bool> is_ymin(N*M); // bottom
00412             std::vector<bool> is_ymax(N*M); // top
00413 
00414             for (unsigned i=0; i<M*N; i++)
00415             {
00416                 is_xmin[i] = (i%M==0);
00417                 is_xmax[i] = ((i+1)%M==0);
00418                 is_ymin[i] = (i%(M*N)<M);
00419                 is_ymax[i] = (i%(M*N)>=(N-1)*M);
00420             }
00421 
00422             for (unsigned i=0; i<mBoxes.size(); i++)
00423             {
00424                 std::set<unsigned> local_boxes;
00425 
00426                 local_boxes.insert(i);
00427 
00428                 // add the box to the left
00429                 if (!is_xmin[i])
00430                 {
00431                     local_boxes.insert(i-1);
00432                 }
00433                 else // Add Periodic Box if needed
00434                 {
00435                     if(mIsPeriodicInX)
00436                     {
00437                         local_boxes.insert(i+M-1);
00438                     }
00439                 }
00440 
00441                 // add the box to the right
00442                 if (!is_xmax[i])
00443                 {
00444                     local_boxes.insert(i+1);
00445                 }
00446                 else // Add Periodic Box if needed
00447                 {
00448                     if(mIsPeriodicInX)
00449                     {
00450                         local_boxes.insert(i-M+1);
00451                     }
00452                 }
00453 
00454                 // add the one below
00455                 if (!is_ymin[i])
00456                 {
00457                     local_boxes.insert(i-M);
00458                 }
00459 
00460                 // add the one above
00461                 if (!is_ymax[i])
00462                 {
00463                     local_boxes.insert(i+M);
00464                 }
00465 
00466                 // add the four corner boxes
00467 
00468                 if ( (!is_xmin[i]) && (!is_ymin[i]) )
00469                 {
00470                     local_boxes.insert(i-1-M);
00471                 }
00472                 if ( (!is_xmin[i]) && (!is_ymax[i]) )
00473                 {
00474                     local_boxes.insert(i-1+M);
00475                 }
00476                 if ( (!is_xmax[i]) && (!is_ymin[i]) )
00477                 {
00478                     local_boxes.insert(i+1-M);
00479                 }
00480                 if ( (!is_xmax[i]) && (!is_ymax[i]) )
00481                 {
00482                     local_boxes.insert(i+1+M);
00483                 }
00484 
00485                 // Add Periodic Corner Boxes if needed
00486                 if(mIsPeriodicInX)
00487                 {
00488                     if( (is_xmin[i]) && (!is_ymin[i]) )
00489                     {
00490                         local_boxes.insert(i-1);
00491                     }
00492                     if ( (is_xmin[i]) && (!is_ymax[i]) )
00493                     {
00494                         local_boxes.insert(i-1+2*M);
00495                     }
00496                     if ( (is_xmax[i]) && (!is_ymin[i]) )
00497                     {
00498                         local_boxes.insert(i+1-2*M);
00499                     }
00500                     if ( (is_xmax[i]) && (!is_ymax[i]) )
00501                     {
00502                         local_boxes.insert(i+1);
00503                     }
00504                 }
00505 
00506                 mLocalBoxes.push_back(local_boxes);
00507             }
00508             break;
00509         }
00510         case 3:
00511         {
00512             mLocalBoxes.clear();
00513 
00514             unsigned M = mNumBoxesEachDirection(0);
00515             unsigned N = mNumBoxesEachDirection(1);
00516             unsigned P = mNumBoxesEachDirection(2);
00517 
00518             std::vector<bool> is_xmin(N*M*P); // far left
00519             std::vector<bool> is_xmax(N*M*P); // far right
00520             std::vector<bool> is_ymin(N*M*P); // nearest
00521             std::vector<bool> is_ymax(N*M*P); // furthest
00522             std::vector<bool> is_zmin(N*M*P); // bottom layer
00523             std::vector<bool> is_zmax(N*M*P); // top layer
00524 
00525             for (unsigned i=0; i<M*N*P; i++)
00526             {
00527                 is_xmin[i] = (i%M==0);
00528                 is_xmax[i] = ((i+1)%M==0);
00529                 is_ymin[i] = (i%(M*N)<M);
00530                 is_ymax[i] = (i%(M*N)>=(N-1)*M);
00531                 is_zmin[i] = (i<M*N);
00532                 is_zmax[i] = (i>=M*N*(P-1));
00533             }
00534 
00535             for (unsigned i=0; i<mBoxes.size(); i++)
00536             {
00537                 std::set<unsigned> local_boxes;
00538 
00539                 // add itself as a local box
00540                 local_boxes.insert(i);
00541 
00542                 // now add all 26 other neighbours.....
00543 
00544                 // add the box left
00545                 if (!is_xmin[i])
00546                 {
00547                     local_boxes.insert(i-1);
00548 
00549                     // plus some others towards the left
00550                     if (!is_ymin[i])
00551                     {
00552                         local_boxes.insert(i-1-M);
00553                     }
00554 
00555                     if (!is_ymax[i])
00556                     {
00557                         local_boxes.insert(i-1+M);
00558                     }
00559 
00560                     if (!is_zmin[i])
00561                     {
00562                         local_boxes.insert(i-1-M*N);
00563                     }
00564 
00565                     if (!is_zmax[i])
00566                     {
00567                         local_boxes.insert(i-1+M*N);
00568                     }
00569                 }
00570 
00571                 // add the box to the right
00572                 if (!is_xmax[i])
00573                 {
00574                     local_boxes.insert(i+1);
00575 
00576                     // plus some others towards the right
00577                     if (!is_ymin[i])
00578                     {
00579                         local_boxes.insert(i+1-M);
00580                     }
00581 
00582                     if (!is_ymax[i])
00583                     {
00584                         local_boxes.insert(i+1+M);
00585                     }
00586 
00587                     if (!is_zmin[i])
00588                     {
00589                         local_boxes.insert(i+1-M*N);
00590                     }
00591 
00592                     if (!is_zmax[i])
00593                     {
00594                         local_boxes.insert(i+1+M*N);
00595                     }
00596                 }
00597 
00598                 // add the boxes next along the y axis
00599                 if (!is_ymin[i])
00600                 {
00601                     local_boxes.insert(i-M);
00602 
00603                     // and more in this plane
00604                     if (!is_zmin[i])
00605                     {
00606                         local_boxes.insert(i-M-M*N);
00607                     }
00608 
00609                     if (!is_zmax[i])
00610                     {
00611                         local_boxes.insert(i-M+M*N);
00612                     }
00613                 }
00614 
00615                 // add the boxes next along the y axis
00616                 if (!is_ymax[i])
00617                 {
00618                     local_boxes.insert(i+M);
00619 
00620                     // and more in this plane
00621                     if (!is_zmin[i])
00622                     {
00623                         local_boxes.insert(i+M-M*N);
00624                     }
00625 
00626                     if (!is_zmax[i])
00627                     {
00628                         local_boxes.insert(i+M+M*N);
00629                     }
00630                 }
00631 
00632                 // add the box directly above
00633                 if (!is_zmin[i])
00634                 {
00635                     local_boxes.insert(i-N*M);
00636                 }
00637 
00638                 // add the box directly below
00639                 if (!is_zmax[i])
00640                 {
00641                     local_boxes.insert(i+N*M);
00642                 }
00643 
00644                 // finally, the 8 corners are left
00645 
00646                 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmin[i]) )
00647                 {
00648                     local_boxes.insert(i-1-M-M*N);
00649                 }
00650 
00651                 if ( (!is_xmin[i]) && (!is_ymin[i]) && (!is_zmax[i]) )
00652                 {
00653                     local_boxes.insert(i-1-M+M*N);
00654                 }
00655 
00656                 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmin[i]) )
00657                 {
00658                     local_boxes.insert(i-1+M-M*N);
00659                 }
00660 
00661                 if ( (!is_xmin[i]) && (!is_ymax[i]) && (!is_zmax[i]) )
00662                 {
00663                     local_boxes.insert(i-1+M+M*N);
00664                 }
00665 
00666                 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmin[i]) )
00667                 {
00668                     local_boxes.insert(i+1-M-M*N);
00669                 }
00670 
00671                 if ( (!is_xmax[i]) && (!is_ymin[i]) && (!is_zmax[i]) )
00672                 {
00673                     local_boxes.insert(i+1-M+M*N);
00674                 }
00675 
00676                 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmin[i]) )
00677                 {
00678                     local_boxes.insert(i+1+M-M*N);
00679                 }
00680 
00681                 if ( (!is_xmax[i]) && (!is_ymax[i]) && (!is_zmax[i]) )
00682                 {
00683                     local_boxes.insert(i+1+M+M*N);
00684                 }
00685 
00686                 mLocalBoxes.push_back(local_boxes);
00687             }
00688             break;
00689         }
00690         default:
00691             NEVER_REACHED;
00692     }
00693 }
00694 
00695 template<unsigned DIM>
00696 std::set<unsigned> BoxCollection<DIM>::GetLocalBoxes(unsigned boxIndex)
00697 {
00698     assert(boxIndex < mLocalBoxes.size());
00699     return mLocalBoxes[boxIndex];
00700 }
00701 
00702 template<unsigned DIM>
00703 const c_vector<double, 2*DIM>& BoxCollection<DIM>::rGetDomainSize() const
00704 {
00705     return mDomainSize;
00706 }
00707 
00708 template<unsigned DIM>
00709 void BoxCollection<DIM>::CalculateNodePairs(std::vector<Node<DIM>*>& rNodes, std::vector<std::pair<Node<DIM>*, Node<DIM>*> >& rNodePairs, std::map<unsigned, std::set<unsigned> >& rNodeNeighbours)
00710 {
00711     rNodePairs.clear();
00712     rNodeNeighbours.clear();
00713 
00714     // Create an empty set of neighbours for each node
00715     for (unsigned node_index=0; node_index<rNodes.size(); node_index++)
00716     {
00717         rNodeNeighbours[node_index] = std::set<unsigned>();
00718     }
00719 
00720     for (unsigned i=0; i<rNodes.size(); i++)
00721     {
00722         unsigned node_index = rNodes[i]->GetIndex();
00723 
00724         // Get the box containing this node
00725         unsigned box_index = CalculateContainingBox(rNodes[i]);
00726 
00727         // Get the local boxes to this node
00728         std::set<unsigned> local_boxes_indices = GetLocalBoxes(box_index);
00729 
00730         // Loop over all the local boxes
00731         for (std::set<unsigned>::iterator box_iter = local_boxes_indices.begin();
00732              box_iter != local_boxes_indices.end();
00733              box_iter++)
00734         {
00735             // Get the set of nodes contained in this box
00736             std::set< Node<DIM>* >& r_contained_nodes = mBoxes[*box_iter].rGetNodesContained();
00737 
00738             // Loop over these nodes
00739             for (typename std::set<Node<DIM>*>::iterator node_iter = r_contained_nodes.begin();
00740                  node_iter != r_contained_nodes.end();
00741                  ++node_iter)
00742             {
00743                 // Get the index of the other node
00744                 unsigned other_node_index = (*node_iter)->GetIndex();
00745 
00746                 // If we're in the same box, then take care not to store the node pair twice
00747                 if (*box_iter == box_index)
00748                 {
00749                     if (other_node_index > rNodes[i]->GetIndex())
00750                     {
00751                         rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>(rNodes[i], (*node_iter)));
00752                         rNodeNeighbours[node_index].insert(other_node_index);
00753                         rNodeNeighbours[other_node_index].insert(node_index);
00754                     }
00755                 }
00756                 else
00757                 {
00758                     rNodePairs.push_back(std::pair<Node<DIM>*, Node<DIM>*>(rNodes[i], (*node_iter)));
00759                     rNodeNeighbours[node_index].insert(other_node_index);
00760                     rNodeNeighbours[other_node_index].insert(node_index);
00761                 }
00762             }
00763         }
00764     }
00765 }
00766 
00768 // Explicit instantiation
00770 
00771 template class BoxCollection<1>;
00772 template class BoxCollection<2>;
00773 template class BoxCollection<3>;

Generated by  doxygen 1.6.2