Chaste Release::3.1
|
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>;