PottsMeshGenerator.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 
00036 #include "PottsMeshGenerator.hpp"
00037 
00038 #include <boost/scoped_array.hpp>
00039 
00040 template<unsigned DIM>
00041 PottsMeshGenerator<DIM>::PottsMeshGenerator(unsigned numNodesAcross, unsigned numElementsAcross, unsigned elementWidth,
00042                                             unsigned numNodesUp, unsigned numElementsUp, unsigned elementHeight,
00043                                             unsigned numNodesDeep, unsigned numElementsDeep, unsigned elementDepth,
00044                                             bool startAtBottomLeft, bool isPeriodicInX, bool isPeriodicInY ,bool isPeriodicInZ)
00045 {
00046     assert(numNodesAcross > 0);
00047     assert(numNodesUp > 0);
00048     assert(numNodesDeep > 0);
00049 
00050     assert(numElementsAcross*elementWidth <= numNodesAcross);
00051     assert(numElementsUp*elementHeight <= numNodesUp);
00052     assert(numElementsDeep*elementDepth <= numNodesDeep);
00053 
00054     std::vector<Node<DIM>*> nodes;
00055     std::vector<PottsElement<DIM>*>  elements;
00056     std::vector<std::set<unsigned> > moore_neighbours;
00057     std::vector<std::set<unsigned> > von_neumann_neighbours;
00058 
00059     unsigned num_nodes = numNodesAcross*numNodesUp*numNodesDeep;
00060 
00061     unsigned next_node_index = 0;
00062     boost::scoped_array<unsigned> node_indices(new unsigned[elementWidth*elementHeight*elementDepth]);
00063     unsigned element_index;
00064 
00065     unsigned index_offset = 0;
00066 
00067     if (!startAtBottomLeft) // Elements in centre of mesh
00068     {
00069         // Calculate the width of the medium on the edge and offset the node index so that the elements are in the centre of the mesh.
00070         unsigned across_gap = (numNodesAcross -  numElementsAcross*elementWidth)/2;
00071         unsigned up_gap = (numNodesUp -  numElementsUp*elementHeight)/2;
00072         unsigned deep_gap = (numNodesDeep -  numElementsDeep*elementDepth)/2;
00073 
00074         index_offset = deep_gap*numNodesAcross*numNodesUp + up_gap*numNodesAcross + across_gap;
00075     }
00076 
00077     /*
00078      * Create the nodes, row by row, from the bottom up
00079      * On the first and last row we have numNodesAcross nodes, all of which are boundary
00080      * nodes. On each interior row we have numNodesAcross nodes, the first and last nodes
00081      * are boundary nodes.
00082      */
00083     for (unsigned k=0; k<numNodesDeep; k++)
00084     {
00085         for (unsigned j=0; j<numNodesUp; j++)
00086         {
00087             for (unsigned i=0; i<numNodesAcross; i++)
00088             {
00089                 bool is_boundary_node=false;
00090                 if (DIM==2)
00091                 {
00092                     is_boundary_node = (j==0 || j==numNodesUp-1 || (i==0 && !isPeriodicInX) || (i==numNodesAcross-1 && !isPeriodicInX) ) ? true : false;
00093                 }
00094                 if (DIM==3)
00095                 {
00096                     is_boundary_node = (j==0 || j==numNodesUp-1 || (i==0 && !isPeriodicInX) || (i==numNodesAcross-1 && !isPeriodicInX) || k==0 || k==numNodesDeep-1) ? true : false;
00097                 }
00098                 Node<DIM>* p_node = new Node<DIM>(next_node_index, is_boundary_node, i, j, k);
00099                 nodes.push_back(p_node);
00100                 next_node_index++;
00101             }
00102         }
00103     }
00104     assert(nodes.size()==num_nodes);
00105 
00106     /*
00107      * Create the elements. The array node_indices contains the
00108      * global node indices, in increasing order.
00109      */
00110     for (unsigned n=0; n<numElementsDeep; n++)
00111     {
00112         for (unsigned j=0; j<numElementsUp; j++)
00113         {
00114             for (unsigned i=0; i<numElementsAcross; i++)
00115             {
00116                 for (unsigned m=0; m<elementDepth; m++)
00117                 {
00118                     for (unsigned l=0; l<elementHeight; l++)
00119                     {
00120                         for (unsigned k=0; k<elementWidth; k++)
00121                         {
00122                             node_indices[m*elementHeight*elementWidth + l*elementWidth + k] = n*elementDepth*numNodesUp*numNodesAcross +
00123                                                                                               j*elementHeight*numNodesAcross +
00124                                                                                               i*elementWidth +
00125                                                                                               m*numNodesAcross*numNodesUp +
00126                                                                                               l*numNodesAcross +
00127                                                                                               k + index_offset;
00128                         }
00129                     }
00130                 }
00131                 std::vector<Node<DIM>*> element_nodes;
00132                 for (unsigned k=0; k<elementDepth*elementHeight*elementWidth; k++)
00133                 {
00134                    element_nodes.push_back(nodes[node_indices[k]]);
00135                 }
00136 
00137                 element_index = n*numElementsAcross*numElementsUp + j*numElementsAcross + i;
00138                 PottsElement<DIM>* p_element = new PottsElement<DIM>(element_index, element_nodes);
00139                 elements.push_back(p_element);
00140             }
00141         }
00142     }
00143 
00144     /*
00145      * Create the neighborhoods of each node
00146      */
00147 
00148     moore_neighbours.resize(num_nodes);
00149     von_neumann_neighbours.resize(num_nodes);
00150 
00151     for (unsigned node_index=0; node_index<num_nodes; node_index++)
00152     {
00153         // Clear the set of neighbouring node indices
00154 
00155         moore_neighbours[node_index].clear();
00156 
00157         switch (DIM)
00158         {
00159             case 2:
00160             {
00161                 assert(DIM == 2);
00162                 /*
00163                  * This stores the available neighbours using the following numbering:
00164                  *
00165                  *  1-----0-----7
00166                  *  |     |     |
00167                  *  |     |     |
00168                  *  2-----x-----6
00169                  *  |     |     |
00170                  *  |     |     |
00171                  *  3-----4-----5
00172                  */
00173 
00174                 // Create a vector of possible neighbouring node indices
00175                 std::vector<unsigned> moore_neighbour_indices_vector(8, node_index);
00176                 moore_neighbour_indices_vector[0] += numNodesAcross;
00177                 moore_neighbour_indices_vector[1] += numNodesAcross - 1;
00178                 moore_neighbour_indices_vector[2] -= 1;
00179                 moore_neighbour_indices_vector[3] -= numNodesAcross + 1;
00180                 moore_neighbour_indices_vector[4] -= numNodesAcross;
00181                 moore_neighbour_indices_vector[5] -= numNodesAcross - 1;
00182                 moore_neighbour_indices_vector[6] += 1;
00183                 moore_neighbour_indices_vector[7] += numNodesAcross + 1;
00184 
00185                 // Work out whether this node lies on any edge of the mesh
00186                 bool on_south_edge = (node_index < numNodesAcross);
00187                 bool on_north_edge = ((int) node_index > (int)numNodesAcross*((int)numNodesUp - 1) - 1);
00188                 bool on_west_edge = (node_index%numNodesAcross == 0);
00189                 bool on_east_edge = (node_index%numNodesAcross == numNodesAcross - 1);
00190 
00191                 if (isPeriodicInX)
00192                 {
00193                     if (on_west_edge)
00194                     {
00195                         moore_neighbour_indices_vector[1] = node_index + 2*numNodesAcross - 1;
00196                         moore_neighbour_indices_vector[2] = node_index + numNodesAcross - 1;
00197                         moore_neighbour_indices_vector[3] = node_index - 1;
00198                     }
00199 
00200                     if (on_east_edge)
00201                     {
00202                         moore_neighbour_indices_vector[5] = node_index - 2*numNodesAcross + 1;
00203                         moore_neighbour_indices_vector[6] = node_index - numNodesAcross + 1;
00204                         moore_neighbour_indices_vector[7] = node_index + 1;
00205                     }
00206                 }
00207 
00208                 if (isPeriodicInY)
00209                 {
00210                     if (on_north_edge)
00211                     {
00212                         moore_neighbour_indices_vector[0] = node_index - numNodesAcross*(numNodesUp-1);
00213                         moore_neighbour_indices_vector[1] = moore_neighbour_indices_vector[0] - 1;
00214                         moore_neighbour_indices_vector[7] = moore_neighbour_indices_vector[0] + 1;
00215 
00216                         if (on_west_edge)
00217                         {
00218                             moore_neighbour_indices_vector[1] = moore_neighbour_indices_vector[1] + numNodesAcross;
00219                         }
00220                         if (on_east_edge)
00221                         {
00222                             moore_neighbour_indices_vector[7] = moore_neighbour_indices_vector[7] - numNodesAcross;
00223                         }
00224                     }
00225 
00226                     if (on_south_edge)
00227                     {
00228                         moore_neighbour_indices_vector[4] = node_index + numNodesAcross*(numNodesUp-1);
00229                         moore_neighbour_indices_vector[3] = moore_neighbour_indices_vector[4] - 1;
00230                         moore_neighbour_indices_vector[5] = moore_neighbour_indices_vector[4] + 1;
00231 
00232                         if (on_west_edge)
00233                         {
00234                             moore_neighbour_indices_vector[3] = moore_neighbour_indices_vector[3] + numNodesAcross;
00235                         }
00236                         if (on_east_edge)
00237                         {
00238                             moore_neighbour_indices_vector[5] = moore_neighbour_indices_vector[5] - numNodesAcross;
00239                         }
00240                     }
00241                 }
00242 
00243                 if (isPeriodicInX)
00244                 {
00245                     on_east_edge = false;
00246                     on_west_edge = false;
00247                 }
00248                 if (isPeriodicInY)
00249                 {
00250                     on_south_edge = false;
00251                     on_north_edge = false;
00252                 }
00253 
00254                 // Create a vector of booleans for which neighbours are available
00255                 // Use the order N, NW, W, SW, S, SE, E, NE
00256                 std::vector<bool> available_neighbours = std::vector<bool>(8, true);
00257                 available_neighbours[0] = !on_north_edge;
00258                 available_neighbours[1] = !(on_north_edge || on_west_edge);
00259                 available_neighbours[2] = !on_west_edge;
00260                 available_neighbours[3] = !(on_south_edge || on_west_edge);
00261                 available_neighbours[4] = !on_south_edge;
00262                 available_neighbours[5] = !(on_south_edge || on_east_edge);
00263                 available_neighbours[6] = !on_east_edge;
00264                 available_neighbours[7] = !(on_north_edge || on_east_edge);
00265 
00266                 // Using neighbour_indices_vector and available_neighbours, store the indices of all available neighbours to the set all_neighbours
00267                 for (unsigned i=0; i<8; i++)
00268                 {
00269                     if (available_neighbours[i])
00270                     {
00271                         assert(moore_neighbour_indices_vector[i] < nodes.size());
00272                         moore_neighbours[node_index].insert(moore_neighbour_indices_vector[i]);
00273                     }
00274                 }
00275                 break;
00276             }
00277             case 3:
00278             {
00279                 assert(DIM ==3);
00280                 /*
00281                  * This stores the available neighbours using the following numbering:
00282                  *                      FRONT           BACK
00283                  *  1-----0-----7   10-----9---16   19----18---25
00284                  *  |     |     |   |     |     |   |     |     |
00285                  *  |     |     |   |     |     |   |     |     |
00286                  *  2-----x-----6   11----8-----15  20----17---24
00287                  *  |     |     |   |     |     |   |     |     |
00288                  *  |     |     |   |     |     |   |     |     |
00289                  *  3-----4-----5   12----13----14  21---22----23
00290                  */
00291 
00292                 // Create a vector of possible neighbouring node indices
00293                 std::vector<unsigned> moore_neighbour_indices_vector(26, node_index);
00294                 moore_neighbour_indices_vector[0] += numNodesAcross;
00295                 moore_neighbour_indices_vector[1] += numNodesAcross - 1;
00296                 moore_neighbour_indices_vector[2] -= 1;
00297                 moore_neighbour_indices_vector[3] -= numNodesAcross + 1;
00298                 moore_neighbour_indices_vector[4] -= numNodesAcross;
00299                 moore_neighbour_indices_vector[5] -= numNodesAcross - 1;
00300                 moore_neighbour_indices_vector[6] += 1;
00301                 moore_neighbour_indices_vector[7] += numNodesAcross + 1;
00302                 moore_neighbour_indices_vector[8] -= numNodesAcross*numNodesUp;
00303                 for (unsigned i=9; i<17; i++)
00304                 {
00305                     moore_neighbour_indices_vector[i] = moore_neighbour_indices_vector[i-9]-numNodesAcross*numNodesUp;
00306                 }
00307                 moore_neighbour_indices_vector[17] += numNodesAcross*numNodesUp;
00308                 for (unsigned i=18; i<26; i++)
00309                 {
00310                     moore_neighbour_indices_vector[i]=moore_neighbour_indices_vector[i-18]+numNodesAcross*numNodesUp;
00311                 }
00312 
00313                 // Work out whether this node lies on any edge of the mesh
00314                 bool on_south_edge = (node_index%(numNodesAcross*numNodesUp)<numNodesAcross);
00315                 bool on_north_edge = (node_index%(numNodesAcross*numNodesUp)>(numNodesAcross*numNodesUp-numNodesAcross-1));
00316                 bool on_west_edge = (node_index%numNodesAcross == 0);
00317                 bool on_east_edge = (node_index%numNodesAcross == numNodesAcross - 1);
00318                 bool on_front_edge = (node_index < numNodesAcross*numNodesUp);
00319                 bool on_back_edge = (node_index > numNodesAcross*numNodesUp*(numNodesDeep-1)-1);
00320 
00321                 if (isPeriodicInX)
00322                 {
00323                     if (on_west_edge)
00324                     {
00325                         moore_neighbour_indices_vector[1] = node_index + 2*numNodesAcross - 1;
00326                         moore_neighbour_indices_vector[2] = node_index + numNodesAcross - 1;
00327                         moore_neighbour_indices_vector[3] = node_index - 1;
00328 
00329                         moore_neighbour_indices_vector[10] = moore_neighbour_indices_vector[1] - numNodesAcross*numNodesUp;
00330                         moore_neighbour_indices_vector[11] = moore_neighbour_indices_vector[2] - numNodesAcross*numNodesUp;
00331                         moore_neighbour_indices_vector[12] = moore_neighbour_indices_vector[3] - numNodesAcross*numNodesUp;
00332 
00333                         moore_neighbour_indices_vector[19] = moore_neighbour_indices_vector[1] + numNodesAcross*numNodesUp;
00334                         moore_neighbour_indices_vector[20] = moore_neighbour_indices_vector[2] + numNodesAcross*numNodesUp;
00335                         moore_neighbour_indices_vector[21] = moore_neighbour_indices_vector[3] + numNodesAcross*numNodesUp;
00336                     }
00337 
00338                     if (on_east_edge)
00339                     {
00340                         moore_neighbour_indices_vector[5] = node_index - 2*numNodesAcross + 1;
00341                         moore_neighbour_indices_vector[6] = node_index - numNodesAcross + 1;
00342                         moore_neighbour_indices_vector[7] = node_index + 1;
00343 
00344                         moore_neighbour_indices_vector[14] = moore_neighbour_indices_vector[5] - numNodesAcross*numNodesUp;
00345                         moore_neighbour_indices_vector[15] = moore_neighbour_indices_vector[6] - numNodesAcross*numNodesUp;
00346                         moore_neighbour_indices_vector[16] = moore_neighbour_indices_vector[7] - numNodesAcross*numNodesUp;
00347 
00348                         moore_neighbour_indices_vector[23] = moore_neighbour_indices_vector[5] + numNodesAcross*numNodesUp;
00349                         moore_neighbour_indices_vector[24] = moore_neighbour_indices_vector[6] + numNodesAcross*numNodesUp;
00350                         moore_neighbour_indices_vector[25] = moore_neighbour_indices_vector[7] + numNodesAcross*numNodesUp;
00351                     }
00352                 }
00353 
00354                 if (isPeriodicInY)
00355                 {
00356                     if (on_north_edge)
00357                     {
00358                         moore_neighbour_indices_vector[0] = node_index - numNodesAcross*(numNodesUp-1);
00359                         moore_neighbour_indices_vector[1] = moore_neighbour_indices_vector[0] - 1;
00360                         moore_neighbour_indices_vector[7] = moore_neighbour_indices_vector[0] + 1;
00361 
00362                         moore_neighbour_indices_vector[10] = moore_neighbour_indices_vector[1] - numNodesAcross*numNodesUp;
00363                         moore_neighbour_indices_vector[9] = moore_neighbour_indices_vector[0] - numNodesAcross*numNodesUp;
00364                         moore_neighbour_indices_vector[16] = moore_neighbour_indices_vector[7] - numNodesAcross*numNodesUp;
00365 
00366                         moore_neighbour_indices_vector[19] = moore_neighbour_indices_vector[1] + numNodesAcross*numNodesUp;
00367                         moore_neighbour_indices_vector[18] = moore_neighbour_indices_vector[0] + numNodesAcross*numNodesUp;
00368                         moore_neighbour_indices_vector[25] = moore_neighbour_indices_vector[7] + numNodesAcross*numNodesUp;
00369 
00370                         if (on_west_edge)
00371                         {
00372                             moore_neighbour_indices_vector[1] = moore_neighbour_indices_vector[1] + numNodesAcross;
00373                             moore_neighbour_indices_vector[10] = moore_neighbour_indices_vector[10] + numNodesAcross;
00374                             moore_neighbour_indices_vector[19] = moore_neighbour_indices_vector[19] + numNodesAcross;
00375                         }
00376                         if (on_east_edge)
00377                         {
00378                             moore_neighbour_indices_vector[7] = moore_neighbour_indices_vector[7] - numNodesAcross;
00379                             moore_neighbour_indices_vector[16] = moore_neighbour_indices_vector[16] - numNodesAcross;
00380                             moore_neighbour_indices_vector[25] = moore_neighbour_indices_vector[25] - numNodesAcross;
00381                         }
00382                     }
00383 
00384                     if (on_south_edge)
00385                     {
00386                         moore_neighbour_indices_vector[4] = node_index + numNodesAcross*(numNodesUp-1);
00387                         moore_neighbour_indices_vector[3] = moore_neighbour_indices_vector[4] - 1;
00388                         moore_neighbour_indices_vector[5] = moore_neighbour_indices_vector[4] + 1;
00389 
00390                         moore_neighbour_indices_vector[12] = moore_neighbour_indices_vector[3] - numNodesAcross*numNodesUp;
00391                         moore_neighbour_indices_vector[13] = moore_neighbour_indices_vector[4] - numNodesAcross*numNodesUp;
00392                         moore_neighbour_indices_vector[14] = moore_neighbour_indices_vector[5] - numNodesAcross*numNodesUp;
00393 
00394                         moore_neighbour_indices_vector[21] = moore_neighbour_indices_vector[3] + numNodesAcross*numNodesUp;
00395                         moore_neighbour_indices_vector[22] = moore_neighbour_indices_vector[4] + numNodesAcross*numNodesUp;
00396                         moore_neighbour_indices_vector[23] = moore_neighbour_indices_vector[5] + numNodesAcross*numNodesUp;
00397 
00398                         if (on_west_edge)
00399                         {
00400                             moore_neighbour_indices_vector[3] = moore_neighbour_indices_vector[3] + numNodesAcross;
00401                             moore_neighbour_indices_vector[12] = moore_neighbour_indices_vector[12] + numNodesAcross;
00402                             moore_neighbour_indices_vector[21] = moore_neighbour_indices_vector[21] + numNodesAcross;
00403                         }
00404                         if (on_east_edge)
00405                         {
00406                             moore_neighbour_indices_vector[5] = moore_neighbour_indices_vector[5] - numNodesAcross;
00407                             moore_neighbour_indices_vector[14] = moore_neighbour_indices_vector[14] - numNodesAcross;
00408                             moore_neighbour_indices_vector[23] = moore_neighbour_indices_vector[23] - numNodesAcross;
00409                         }
00410                     }
00411                 }
00412 
00413                 if (isPeriodicInZ)
00414                 {
00415                     if (on_back_edge)
00416                     {
00417                         moore_neighbour_indices_vector[17] = node_index - numNodesAcross*numNodesUp*(numNodesDeep-1);
00418                         moore_neighbour_indices_vector[20] = moore_neighbour_indices_vector[17] - 1;
00419                         moore_neighbour_indices_vector[24] = moore_neighbour_indices_vector[17] + 1;
00420 
00421                         moore_neighbour_indices_vector[21] = moore_neighbour_indices_vector[20] - numNodesAcross;
00422                         moore_neighbour_indices_vector[22] = moore_neighbour_indices_vector[17] - numNodesAcross;
00423                         moore_neighbour_indices_vector[23] = moore_neighbour_indices_vector[24] - numNodesAcross;
00424 
00425                         moore_neighbour_indices_vector[19] = moore_neighbour_indices_vector[20] + numNodesAcross;
00426                         moore_neighbour_indices_vector[18] = moore_neighbour_indices_vector[17] + numNodesAcross;
00427                         moore_neighbour_indices_vector[25] = moore_neighbour_indices_vector[24] + numNodesAcross;
00428 
00429                         if (on_west_edge)
00430                         {
00431                             moore_neighbour_indices_vector[19] = moore_neighbour_indices_vector[19] + numNodesAcross;
00432                             moore_neighbour_indices_vector[20] = moore_neighbour_indices_vector[20] + numNodesAcross;
00433                             moore_neighbour_indices_vector[21] = moore_neighbour_indices_vector[21] + numNodesAcross;
00434                         }
00435                         if (on_east_edge)
00436                         {
00437                             moore_neighbour_indices_vector[23] = moore_neighbour_indices_vector[23] - numNodesAcross;
00438                             moore_neighbour_indices_vector[24] = moore_neighbour_indices_vector[24] - numNodesAcross;
00439                             moore_neighbour_indices_vector[25] = moore_neighbour_indices_vector[25] - numNodesAcross;
00440                         }
00441 
00442                         if (on_south_edge)
00443                         {
00444                             moore_neighbour_indices_vector[21] = moore_neighbour_indices_vector[21] + numNodesAcross*numNodesUp;
00445                             moore_neighbour_indices_vector[22] = moore_neighbour_indices_vector[22] + numNodesAcross*numNodesUp;
00446                             moore_neighbour_indices_vector[23] = moore_neighbour_indices_vector[23] + numNodesAcross*numNodesUp;
00447                         }
00448 
00449                         if (on_north_edge)
00450                         {
00451                             moore_neighbour_indices_vector[18] = moore_neighbour_indices_vector[18] - numNodesAcross*numNodesUp;
00452                             moore_neighbour_indices_vector[19] = moore_neighbour_indices_vector[19] - numNodesAcross*numNodesUp;
00453                             moore_neighbour_indices_vector[25] = moore_neighbour_indices_vector[25] - numNodesAcross*numNodesUp;
00454                         }
00455                     }
00456 
00457                     if (on_front_edge)
00458                     {
00459                         moore_neighbour_indices_vector[8] = node_index + numNodesAcross*numNodesUp*(numNodesDeep-1);
00460                         moore_neighbour_indices_vector[11] = moore_neighbour_indices_vector[8] - 1;
00461                         moore_neighbour_indices_vector[15] = moore_neighbour_indices_vector[8] + 1;
00462 
00463                         moore_neighbour_indices_vector[12] = moore_neighbour_indices_vector[11] - numNodesAcross;
00464                         moore_neighbour_indices_vector[13] = moore_neighbour_indices_vector[8] - numNodesAcross;
00465                         moore_neighbour_indices_vector[14] = moore_neighbour_indices_vector[15] - numNodesAcross;
00466 
00467                         moore_neighbour_indices_vector[10] = moore_neighbour_indices_vector[11] + numNodesAcross;
00468                         moore_neighbour_indices_vector[9] = moore_neighbour_indices_vector[8] + numNodesAcross;
00469                         moore_neighbour_indices_vector[16] = moore_neighbour_indices_vector[15] + numNodesAcross;
00470 
00471                         if (on_west_edge)
00472                         {
00473                             moore_neighbour_indices_vector[10] = moore_neighbour_indices_vector[10] + numNodesAcross;
00474                             moore_neighbour_indices_vector[11] = moore_neighbour_indices_vector[11] + numNodesAcross;
00475                             moore_neighbour_indices_vector[12] = moore_neighbour_indices_vector[12] + numNodesAcross;
00476                         }
00477                         if (on_east_edge)
00478                         {
00479                             moore_neighbour_indices_vector[14] = moore_neighbour_indices_vector[14] - numNodesAcross;
00480                             moore_neighbour_indices_vector[15] = moore_neighbour_indices_vector[15] - numNodesAcross;
00481                             moore_neighbour_indices_vector[16] = moore_neighbour_indices_vector[16] - numNodesAcross;
00482                         }
00483 
00484                         if (on_south_edge)
00485                         {
00486                             moore_neighbour_indices_vector[12] = moore_neighbour_indices_vector[12] + numNodesAcross*numNodesUp;
00487                             moore_neighbour_indices_vector[13] = moore_neighbour_indices_vector[13] + numNodesAcross*numNodesUp;
00488                             moore_neighbour_indices_vector[14] = moore_neighbour_indices_vector[14] + numNodesAcross*numNodesUp;
00489                         }
00490 
00491                         if (on_north_edge)
00492                         {
00493                             moore_neighbour_indices_vector[9] = moore_neighbour_indices_vector[9] - numNodesAcross*numNodesUp;
00494                             moore_neighbour_indices_vector[10] = moore_neighbour_indices_vector[10] - numNodesAcross*numNodesUp;
00495                             moore_neighbour_indices_vector[16] = moore_neighbour_indices_vector[16] - numNodesAcross*numNodesUp;
00496                         }
00497                     }
00498                 }
00499 
00500                 if (isPeriodicInX)
00501                 {
00502                     on_east_edge = false;
00503                     on_west_edge = false;
00504                 }
00505                 if (isPeriodicInY)
00506                 {
00507                     on_south_edge = false;
00508                     on_north_edge = false;
00509                 }
00510                 if (isPeriodicInZ)
00511                 {
00512                     on_front_edge = false;
00513                     on_back_edge = false;
00514                 }
00515 
00516                 // Create a vector of booleans for which neighbours are available
00517                 // Use the order N, NW, W, SW, S, SE, E, NE
00518                 std::vector<bool> available_neighbours = std::vector<bool>(26, true);
00519                 available_neighbours[0] = !on_north_edge;
00520                 available_neighbours[1] = !(on_north_edge || on_west_edge);
00521                 available_neighbours[2] = !on_west_edge;
00522                 available_neighbours[3] = !(on_south_edge || on_west_edge);
00523                 available_neighbours[4] = !on_south_edge;
00524                 available_neighbours[5] = !(on_south_edge || on_east_edge);
00525                 available_neighbours[6] = !on_east_edge;
00526                 available_neighbours[7] = !(on_north_edge || on_east_edge);
00527                 available_neighbours[8] = !(on_front_edge);
00528                 for (unsigned i=9; i<17; i++)
00529                 {
00530                     available_neighbours[i] = (available_neighbours[i-9] && !(on_front_edge));
00531                 }
00532                 available_neighbours[17] = !(on_back_edge);
00533                 for (unsigned i=18; i<26; i++)
00534                 {
00535                     available_neighbours[i] = (available_neighbours[i-18] && !(on_back_edge));
00536                 }
00537 
00538                 // Using neighbour_indices_vector and available_neighbours, store the indices of all available neighbours to the set all_neighbours
00539                 for (unsigned i=0; i<26; i++)
00540                 {
00541                     if (available_neighbours[i] && moore_neighbour_indices_vector[i] < numNodesAcross*numNodesUp*numNodesDeep)
00542                     {
00543                         assert(moore_neighbour_indices_vector[i] < nodes.size());
00544                         moore_neighbours[node_index].insert(moore_neighbour_indices_vector[i]);
00545                     }
00546                 }
00547                 break;
00548             }
00549             default:
00550                 NEVER_REACHED;
00551         }
00552 
00553         // Clear the set of neighbouring node indices
00554         von_neumann_neighbours[node_index].clear();
00555 
00556         switch (DIM)
00557         {
00558             case 2:
00559             {
00560                 assert(DIM == 2);
00561                 /*
00562                  * This stores the available neighbours using the following numbering:
00563                  *
00564                  *        0
00565                  *        |
00566                  *        |
00567                  *  1-----x-----3
00568                  *        |
00569                  *        |
00570                  *        2
00571                  */
00572                 // Create a vector of possible neighbouring node indices
00573                 std::vector<unsigned> von_neumann_neighbour_indices_vector(4, node_index);
00574                 von_neumann_neighbour_indices_vector[0] += numNodesAcross;
00575                 von_neumann_neighbour_indices_vector[1] -= 1;
00576                 von_neumann_neighbour_indices_vector[2] -= numNodesAcross;
00577                 von_neumann_neighbour_indices_vector[3] += 1;
00578 
00579                 // Work out whether this node lies on any edge of the mesh
00580                 bool on_south_edge = (node_index < numNodesAcross);
00581                 bool on_north_edge = ((int)node_index > (int)numNodesAcross*((int)numNodesUp - 1) - 1);
00582                 bool on_west_edge = (node_index%numNodesAcross == 0);
00583                 bool on_east_edge = (node_index%numNodesAcross == numNodesAcross - 1);
00584 
00585                 if (isPeriodicInX)
00586                 {
00587                     if (on_west_edge)
00588                     {
00589                         von_neumann_neighbour_indices_vector[1] = node_index + numNodesAcross - 1;
00590                         on_west_edge = false;
00591                     }
00592 
00593                     if (on_east_edge)
00594                     {
00595                         von_neumann_neighbour_indices_vector[3] = node_index - numNodesAcross + 1;
00596                         on_east_edge = false;
00597                     }
00598                 }
00599 
00600                 if (isPeriodicInY)
00601                 {
00602                     if (on_north_edge)
00603                     {
00604                         von_neumann_neighbour_indices_vector[0] = node_index - numNodesAcross*(numNodesUp-1);
00605                         on_north_edge = false;
00606                     }
00607 
00608                     if (on_south_edge)
00609                     {
00610                         von_neumann_neighbour_indices_vector[2] = node_index + numNodesAcross*(numNodesUp-1);
00611                         on_south_edge = false;
00612                     }
00613                 }
00614 
00615                 // Create a vector of booleans for which neighbours are available
00616                 // Use the order N, W, S, E
00617                 std::vector<bool> available_neighbours = std::vector<bool>(2*DIM, true);
00618                 available_neighbours[0] = !on_north_edge;
00619                 available_neighbours[1] = !on_west_edge;
00620                 available_neighbours[2] = !on_south_edge;
00621                 available_neighbours[3] = !on_east_edge;
00622 
00623                 // Using von_neumann_neighbour_indices_vector and available_neighbours, store the indices of all available neighbours to the set all_neighbours
00624                 for (unsigned i=0; i<4; i++)
00625                 {
00626                     if (available_neighbours[i])
00627                     {
00628                         assert(von_neumann_neighbour_indices_vector[i] < nodes.size());
00629                         von_neumann_neighbours[node_index].insert(von_neumann_neighbour_indices_vector[i]);
00630                     }
00631                 }
00632                 break;
00633             }
00634             case 3:
00635             {
00636                 assert(DIM == 3);
00637 
00638                 /*
00639                  * This stores the available neighbours using the following numbering:
00640                  *
00641                  *        0  5
00642                  *        | /
00643                  *        |/
00644                  *  1-----x-----3
00645                  *      / |
00646                  *     /  |
00647                  *    4   2
00648                  */
00649                 // Create a vector of possible neighbouring node indices
00650                 std::vector<unsigned> von_neumann_neighbour_indices_vector(6, node_index);
00651                 von_neumann_neighbour_indices_vector[0] += numNodesAcross;
00652                 von_neumann_neighbour_indices_vector[1] -= 1;
00653                 von_neumann_neighbour_indices_vector[2] -= numNodesAcross;
00654                 von_neumann_neighbour_indices_vector[3] += 1;
00655                 von_neumann_neighbour_indices_vector[4] -= numNodesAcross*numNodesUp;
00656                 von_neumann_neighbour_indices_vector[5] += numNodesAcross*numNodesUp;
00657 
00658                 // Work out whether this node lies on any edge of the mesh
00659                 bool on_south_edge = (node_index%(numNodesAcross*numNodesUp)<numNodesAcross);
00660                 bool on_north_edge = (node_index%(numNodesAcross*numNodesUp)>(numNodesAcross*numNodesUp-numNodesAcross-1));
00661                 bool on_west_edge = (node_index%numNodesAcross== 0);
00662                 bool on_east_edge = (node_index%numNodesAcross == numNodesAcross - 1);
00663                 bool on_front_edge = (node_index < numNodesAcross*numNodesUp);
00664                 bool on_back_edge = (node_index > numNodesAcross*numNodesUp*(numNodesDeep-1)-1);
00665 
00666                 if (isPeriodicInX)
00667                 {
00668                     if (on_west_edge)
00669                     {
00670                         von_neumann_neighbour_indices_vector[1] = node_index + numNodesAcross - 1;
00671                         on_west_edge = false;
00672                     }
00673 
00674                     if (on_east_edge)
00675                     {
00676                         von_neumann_neighbour_indices_vector[3] = node_index - numNodesAcross + 1;
00677                         on_east_edge = false;
00678                     }
00679                 }
00680 
00681                 if (isPeriodicInY)
00682                 {
00683                     if (on_north_edge)
00684                     {
00685                         von_neumann_neighbour_indices_vector[0] = node_index - numNodesAcross*(numNodesUp-1);
00686                         on_north_edge = false;
00687                     }
00688 
00689                     if (on_south_edge)
00690                     {
00691                         von_neumann_neighbour_indices_vector[2] = node_index + numNodesAcross*(numNodesUp-1);
00692                         on_south_edge = false;
00693                     }
00694                 }
00695 
00696                 if (isPeriodicInZ)
00697                 {
00698                     if (on_front_edge)
00699                     {
00700                         von_neumann_neighbour_indices_vector[4] = node_index + numNodesAcross*numNodesUp*(numNodesDeep-1);
00701                         on_front_edge = false;
00702                     }
00703 
00704                     if (on_back_edge)
00705                     {
00706                         von_neumann_neighbour_indices_vector[5] = node_index - numNodesAcross*numNodesUp*(numNodesDeep-1);
00707                         on_back_edge = false;
00708                     }
00709                 }
00710 
00711                 // Create a vector of booleans for which neighbours are available
00712                 // Use the order N, W, S, E, F, B
00713                 std::vector<bool> available_neighbours = std::vector<bool>(2*DIM, true);
00714                 available_neighbours[0] = !on_north_edge;
00715                 available_neighbours[1] = !on_west_edge;
00716                 available_neighbours[2] = !on_south_edge;
00717                 available_neighbours[3] = !on_east_edge;
00718                 available_neighbours[4] = !on_front_edge;
00719                 available_neighbours[5] = !on_back_edge;
00720 
00721                 // Using von_neumann_neighbour_indices_vector and available_neighbours, store the indices of all available neighbours to the set all_neighbours
00722                 for (unsigned i=0; i<6; i++)
00723                 {
00724                     if (available_neighbours[i] && von_neumann_neighbour_indices_vector[i]<numNodesAcross*numNodesUp*numNodesDeep)
00725                     {
00726                         assert(von_neumann_neighbour_indices_vector[i] < nodes.size());
00727                         von_neumann_neighbours[node_index].insert(von_neumann_neighbour_indices_vector[i]);
00728                     }
00729                 }
00730                 break;
00731             }
00732             default:
00733                 NEVER_REACHED;
00734         }
00735     }
00736 
00737     mpMesh = new PottsMesh<DIM>(nodes, elements, von_neumann_neighbours, moore_neighbours);
00738 }
00739 
00740 template<unsigned DIM>
00741 PottsMeshGenerator<DIM>::~PottsMeshGenerator()
00742 {
00743     delete mpMesh;
00744 }
00745 
00746 template<unsigned DIM>
00747 PottsMesh<DIM>* PottsMeshGenerator<DIM>::GetMesh()
00748 {
00749     return mpMesh;
00750 }
00751 
00753 // Explicit instantiation
00755 
00756 template class PottsMeshGenerator<1>;
00757 template class PottsMeshGenerator<2>;
00758 template class PottsMeshGenerator<3>;

Generated by  doxygen 1.6.2