MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /* ***************************************************************** 00002 MESQUITE -- The Mesh Quality Improvement Toolkit 00003 00004 Copyright 2004 Lawrence Livermore National Laboratory. Under 00005 the terms of Contract B545069 with the University of Wisconsin -- 00006 Madison, Lawrence Livermore National Laboratory retains certain 00007 rights in this software. 00008 00009 This library is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU Lesser General Public 00011 License as published by the Free Software Foundation; either 00012 version 2.1 of the License, or (at your option) any later version. 00013 00014 This library is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License 00020 (lgpl.txt) along with this library; if not, write to the Free Software 00021 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 00023 [email protected] 00024 00025 ***************************************************************** */ 00026 00027 #ifndef MESQUITE_TOPOLOGY_INFO_HPP 00028 #define MESQUITE_TOPOLOGY_INFO_HPP 00029 00030 #include "Mesquite.hpp" 00031 #include "Sample.hpp" 00032 #include <cstring> 00033 00034 namespace MBMesquite 00035 { 00036 00037 class MsqError; 00038 00039 /** \brief Information about different element topologies */ 00040 class MESQUITE_EXPORT TopologyInfo 00041 { 00042 public: 00043 static const char* name( EntityTopology topo ) 00044 { 00045 return topo > MIXED ? 0 : instance.longNames[topo]; 00046 } 00047 static const char* short_name( EntityTopology topo ) 00048 { 00049 return topo > MIXED ? 0 : instance.shortNames[topo]; 00050 } 00051 00052 /** \brief Dimension of element topology */ 00053 static unsigned dimension( EntityTopology topo ) 00054 { 00055 return topo >= MIXED ? 0 : instance.dimMap[topo]; 00056 } 00057 00058 /** \brief Number of adjacent entities of a specified dimension 00059 * 00060 * For a given element topology, get the number of adjacent entities 00061 * of the specified dimension. 00062 */ 00063 static unsigned adjacent( EntityTopology topo, unsigned dimension ) 00064 { 00065 return ( topo >= MIXED ) ? 0 : instance.adjMap[topo][dimension]; 00066 } 00067 00068 /** \brief Get number of sides a given topology type has 00069 * 00070 * Get the number of sides for a given element topology. Returns 00071 * the number of adjacent entities of one less dimension. The number 00072 * of faces for a volume element and the number of edges for a face 00073 * element 00074 */ 00075 static unsigned sides( EntityTopology topo ) 00076 { 00077 return ( topo >= MIXED || instance.dimMap[topo] < 1 ) ? 0 : instance.adjMap[topo][instance.dimMap[topo] - 1]; 00078 } 00079 00080 /** \brief Get the number of defining vertices for a given element topology 00081 * 00082 * Get the number of corner vertices necessary to define an element 00083 * of the specified topology. This is the number of nodes a linear 00084 * element of the specified topology will have. 00085 */ 00086 static unsigned corners( EntityTopology topo ) 00087 { 00088 return adjacent( topo, 0 ); 00089 } 00090 00091 /** \brief Get the number of edges in a given topology */ 00092 static unsigned edges( EntityTopology topo ) 00093 { 00094 return adjacent( topo, 1 ); 00095 } 00096 00097 /** \brief Get the number of faces in a given topology */ 00098 static unsigned faces( EntityTopology topo ) 00099 { 00100 return adjacent( topo, 2 ); 00101 } 00102 00103 /** \brief Check which mid-nodes a higher-order element has. 00104 * 00105 * Assuming at most one mid-node per sub-entity per dimension 00106 * (i.e. at most one mid-node per edge, at most one mid-node per face, etc.) 00107 * determine which mid-nodes are present given the topology 00108 * and total number of nodes. 00109 */ 00110 static void higher_order( EntityTopology topo, 00111 unsigned num_nodes, 00112 bool& midedge, 00113 bool& midface, 00114 bool& midvol, 00115 MsqError& err ); 00116 00117 /** \brief Check which mid-nodes a higher-order element has. 00118 * 00119 * Assuming at most one mid-node per sub-entity per dimension 00120 * (i.e. at most one mid-node per edge, at most one mid-node per face, etc.) 00121 * determine which mid-nodes are present given the topology 00122 * and total number of nodes. This function is similar to the 00123 * previous one, except that that it returns a set of bits, one per 00124 * side dimension, rather than separate bool values. If the bit at position 00125 * one (the second least significant bit) has a value of one, then the 00126 * element has mid-edge nodes. If the bit at position two (the third to 00127 * least signficiant bit) has a value of one then the element has mid-face 00128 * nodes. 00129 *\code 00130 * int ho = TopologyInfo::higher_order( topo, num_nodes, err ); 00131 * bool have_midedge = !!(ho & 1<<1); 00132 * bool have_midface = !!(ho & 1<<2); 00133 * bool have_midvol = !!(ho & 1<<3); 00134 *\endocde 00135 * 00136 * The advantange of this form of the function over the previous is 00137 * that a) it is possible to check for mid-nodes on sub-entities of 00138 * a varialbe dimension 'd': 00139 *\code 00140 * if (ho & (1<<d)) { ... } 00141 *\code 00142 * and b) it is convienent to test if an element has any higher-order 00143 * nodes: 00144 *\code 00145 * int ho = TopologyInfo::higher_order( topo, num_nodes, err ); 00146 * if (!ho) // if linear element 00147 * { ... } 00148 *\endocde 00149 */ 00150 static int higher_order( EntityTopology topo, unsigned num_nodes, MsqError& err ); 00151 00152 /**\brief Given a side, return index of mid-vertex for that side. 00153 * 00154 * Given a side specification (e.g. the first edge), return the 00155 * index of of the correponding mid-side node in the canoncial 00156 * ordering of the element connectivity. Returns -1 if the element 00157 * doesn't have the specified mid-side node. 00158 * 00159 *\param topo The element topology 00160 *\param num_nodes The number of nodes in the element type. 00161 *\param side_dimension The dimension of the side (e.g. 1 = edge, 2 = face) 00162 *\param side_number The number of the side (e.g. 0 for first edge/face, etc.) 00163 *\return Index (zero-based position) of higher-order node in canonical 00164 * ordering of element connectivity, or -1 of element type contains 00165 * no such node. 00166 */ 00167 static int higher_order_from_side( EntityTopology topo, 00168 unsigned num_nodes, 00169 unsigned side_dimension, 00170 unsigned side_number, 00171 MsqError& err ); 00172 00173 /**\brief Get side given a higher-order node */ 00174 static void side_from_higher_order( EntityTopology topo, 00175 unsigned num_nodes, 00176 unsigned node_number, 00177 unsigned& side_dim_out, 00178 unsigned& side_num_out, 00179 MsqError& err ); 00180 00181 /** Get logical position given an element type node node index*/ 00182 static inline Sample sample_from_node( EntityTopology topo, 00183 unsigned num_nodes, 00184 unsigned node_number, 00185 MsqError& err ) 00186 { 00187 unsigned dim, num; 00188 side_from_higher_order( topo, num_nodes, node_number, dim, num, err ); 00189 return Sample( dim, num ); 00190 } 00191 /** Get node index from logical position */ 00192 static inline int node_from_sample( EntityTopology topo, unsigned num_nodes, Sample sample, MsqError& err ) 00193 { 00194 return higher_order_from_side( topo, num_nodes, sample.dimension, sample.number, err ); 00195 } 00196 /**\brief Get indices of edge ends in element connectivity array 00197 * 00198 * Given an edge number in (0,edges(type)], return which positions 00199 * in the connectivity list for the element type correspond to the 00200 * end vertices of that edge. 00201 */ 00202 static const unsigned* edge_vertices( EntityTopology topo, unsigned edge_number, MsqError& err ); 00203 static const unsigned* edge_vertices( EntityTopology topo, unsigned edge_number ); 00204 00205 /**\brief Get face corner indices in element connectivity array 00206 * 00207 * Given an face number in (0,faces(type)], return which positions 00208 * in the connectivity list for the element type correspond to the 00209 * vertices of that face, ordered in a counter-clockwise cycle 00210 * around a vector pointing out of the element for an ideal element. 00211 */ 00212 static const unsigned* face_vertices( EntityTopology topo, 00213 unsigned face_number, 00214 unsigned& num_vertices_out, 00215 MsqError& err ); 00216 static const unsigned* face_vertices( EntityTopology topo, unsigned face_number, unsigned& num_vertices_out ); 00217 00218 /**\brief Get corner indices of side 00219 * 00220 * Get the indices into element connectivity list for the 00221 * corners/ends of the specified side of the element. 00222 * edge_vertices() and face_vertices() are special cases 00223 * of this method. 00224 * 00225 * If the passed dimension equals that of the specified topology, 00226 * the side number is ignored and all the corners of the 00227 * element are returned. Fails if side dimension 00228 * greater than the dimension of the specified topology type. 00229 */ 00230 static const unsigned* side_vertices( EntityTopology topo, 00231 unsigned side_dimension, 00232 unsigned side_number, 00233 unsigned& num_verts_out, 00234 MsqError& err ); 00235 static const unsigned* side_vertices( EntityTopology topo, 00236 unsigned side_dimension, 00237 unsigned side_number, 00238 unsigned& num_verts_out ); 00239 00240 /**\brief Return which side the specified mid-node lies on 00241 * 00242 * Given an non-linear element type (specified by the 00243 * topology and length of the connectiivty array) and the 00244 * index of a node in the element's connectivity array, 00245 * return the lower-dimension entity (side) of the element 00246 * the mid-node lies on. 00247 * 00248 *\param topo Element topology 00249 *\param connectivity_length Number of nodes in element 00250 *\param node_index Which node of the element 00251 *\param side_dimension_out The dimension of the side containing the 00252 * midnode (0 = vertex, 1 = edge, 2 = face, 3 = volume) 00253 *\param side_number_out The canonical number of the side 00254 */ 00255 static void side_number( EntityTopology topo, 00256 unsigned connectivity_length, 00257 unsigned node_index, 00258 unsigned& side_dimension_out, 00259 unsigned& side_number_out, 00260 MsqError& err ); 00261 00262 /**\brief Get adjacent corner vertices 00263 * 00264 * Given the index of a vertex in an element, get the list of 00265 * indices corresponding to the adjacent corner vertices. 00266 * 00267 * Adjcent corner vertex indices are returned in the proper 00268 * order for constructing the active matrix for the corner. 00269 * 00270 * Given the array v of all vertices in the patch, the array v_i 00271 * containing the connectivity list for an element as 00272 * indices into v, and adj as the result of this function for some 00273 * corner of the element, the corresponding active matrix A for 00274 * that corner can be constructed as: 00275 * Matrix3D A; 00276 * A.set_column( 0, v[v_i[adj[0]]] - v[v_i[0]] ); 00277 * A.set_column( 1, v[v_i[adj[1]]] - v[v_i[0]] ); 00278 * A.set_column( 2, v[v_i[adj[2]]] - v[v_i[0]] ); 00279 * 00280 *\param topo The element type 00281 *\param index The index of a corner vertex 00282 *\param num_adj_out The number of adjacent vertices (output) 00283 *\return The array of vertex indices 00284 */ 00285 static const unsigned* adjacent_vertices( EntityTopology topo, unsigned index, unsigned& num_adj_out ); 00286 00287 /**\brief Get reverse adjacency offsets 00288 * 00289 * Get reverse mapping of results from adjacent_vertices(). 00290 * 00291 * Let i be the input vertex index. For each vertex index j 00292 * for which the result of adjacent_vertices() contains i, return 00293 * the offset into that result at which i would occur. The 00294 * results are returned in the same order as each j is returned 00295 * in the results of adjacent_vertices(...,i,...). Thus the 00296 * combination of the results of adjacent_vertices(...,i,...) 00297 * and this method provide a reverse mapping of the results of 00298 * adjacent_vertices(...,j,...) for i in all j. 00299 * 00300 * Given: 00301 * const unsigned *a, *b, *r; 00302 * unsigned n, nn, c = corners(type); 00303 * a = adjacent_vertices( type, i, n ); // for any i < c 00304 * r = reverse_vertex_adjacency_offsets( type, i, n ); 00305 * b = adjacent_vertices( type, a[k], nn ); // for any k < n 00306 * Then: 00307 * b[r[k]] == i 00308 */ 00309 static const unsigned* reverse_vertex_adjacency_offsets( EntityTopology topo, 00310 unsigned index, 00311 unsigned& num_idx_out ); 00312 00313 /**\brief Find which edge of an element has the passed vertex indices 00314 * 00315 * Find which edge of the element cooresponds to a list of positions 00316 * in the canonical element ordering. 00317 *\param topo The element type 00318 *\param edge_vertices The array of side vertex indices 00319 *\param reversed_out True if edge is reversed wrt edge_vertices 00320 *\return The edge number. 00321 */ 00322 static unsigned find_edge( EntityTopology topo, const unsigned* edge_vertices, bool& reversed_out, MsqError& err ); 00323 00324 /**\brief Find which face of an element has the passed vertex indices 00325 * 00326 * Find which face of the element cooresponds to a list of positions 00327 * in the canonical element ordering. 00328 *\param topo The element type 00329 *\param face_vertices The array of face vertex indices 00330 *\param num_face_vertices The length of face_vertices 00331 *\param reversed_out True if face is reversed wrt face_vertices 00332 *\return The face number. 00333 */ 00334 static unsigned find_face( EntityTopology topo, 00335 const unsigned* face_vertices, 00336 unsigned num_face_vertices, 00337 bool& reversed_out, 00338 MsqError& err ); 00339 00340 /**\brief Find which side of an element has the passed vertex indices 00341 * 00342 * Find which side of the element cooresponds to a list of positions 00343 * in the canonical element ordering. 00344 *\param topo The element type 00345 *\param side_vertices The array of side vertex indices 00346 *\param num_vertices The length of side_vertices 00347 *\param dimension_out The dimension of the side 00348 *\param number_out The enumerated index for the side 00349 *\param reversed_out True if side is reversed wrt side_vertices 00350 */ 00351 static void find_side( EntityTopology topo, 00352 const unsigned* side_vertices, 00353 unsigned num_vertices, 00354 unsigned& dimension_out, 00355 unsigned& number_out, 00356 bool& reversed_out, 00357 MsqError& err ); 00358 00359 /**\brief Test if two elements share lower-order topology 00360 * 00361 * Test if two elements share lower-order topology (e.g. 00362 * whether or not two tetrahedra share an edge.) 00363 * 00364 * That is compare the 'element_1_side_number'-th lower order 00365 * topology of dimension 'side_dimension' on element 1 with the 00366 * 'element_2_side_number'-th lower order topology of dimension 00367 *'side_dimension' on element 2 00368 * 00369 *\param element_1_vertices The connectivity of the first element 00370 *\param element_1_topology The type of the first element 00371 *\param element_1_side_number Which lower-order topology to compare 00372 *\param element_2_vertices The connectivity of the second element 00373 *\param element_2_topology The type of the second element 00374 *\param element_2_side_number Whcih lower-order topology to compare 00375 *\param side_dimension The dimension of the lower-order topology 00376 */ 00377 static bool compare_sides( const size_t* element_1_vertices, 00378 EntityTopology element_1_topology, 00379 unsigned element_1_side_number, 00380 const size_t* element_2_vertices, 00381 EntityTopology element_2_topology, 00382 unsigned element_2_side_number, 00383 unsigned side_dimension, 00384 MsqError& err ); 00385 00386 private: 00387 enum 00388 { 00389 MAX_CORNER = 8, 00390 MAX_EDGES = 12, 00391 MAX_FACES = 6, 00392 MAX_FACE_CONN = 5, 00393 MAX_VERT_ADJ = 4, 00394 FIRST_FACE = TRIANGLE, 00395 LAST_FACE = QUADRILATERAL, 00396 FIRST_VOL = TETRAHEDRON, 00397 LAST_VOL = PYRAMID 00398 }; 00399 00400 unsigned char dimMap[MIXED]; /**< Get dimension of entity given topology */ 00401 unsigned char adjMap[MIXED][4]; /**< Get number of adj entities of dimension 0, 1 and dimension 2 */ 00402 /** Vertex indices for element edges */ 00403 unsigned edgeMap[LAST_VOL - FIRST_FACE + 1][MAX_EDGES][2]; 00404 /** Vertex indices for element faces */ 00405 unsigned faceMap[LAST_VOL - FIRST_VOL + 1][MAX_FACES][MAX_FACE_CONN]; 00406 /** Vertex-Vertex adjacency map */ 00407 unsigned vertAdjMap[LAST_VOL - FIRST_FACE + 1][MAX_CORNER][MAX_VERT_ADJ + 1]; 00408 /** Reverse Vertex-Vertex adjacency index map */ 00409 unsigned revVertAdjIdx[LAST_VOL - FIRST_FACE + 1][MAX_CORNER][MAX_VERT_ADJ + 1]; 00410 00411 const char* longNames[MIXED + 1]; 00412 const char* shortNames[MIXED + 1]; 00413 00414 TopologyInfo(); 00415 00416 static TopologyInfo instance; 00417 }; 00418 00419 } // namespace MBMesquite 00420 00421 #endif