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