MOAB: Mesh Oriented datABase
(version 5.3.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 kraftche@cae.wisc.edu 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, unsigned num_nodes, bool& midedge, bool& midface, bool& midvol, 00111 MsqError& err ); 00112 00113 /** \brief Check which mid-nodes a higher-order element has. 00114 * 00115 * Assuming at most one mid-node per sub-entity per dimension 00116 * (i.e. at most one mid-node per edge, at most one mid-node per face, etc.) 00117 * determine which mid-nodes are present given the topology 00118 * and total number of nodes. This function is similar to the 00119 * previous one, except that that it returns a set of bits, one per 00120 * side dimension, rather than separate bool values. If the bit at position 00121 * one (the second least significant bit) has a value of one, then the 00122 * element has mid-edge nodes. If the bit at position two (the third to 00123 * least signficiant bit) has a value of one then the element has mid-face 00124 * nodes. 00125 *\code 00126 * int ho = TopologyInfo::higher_order( topo, num_nodes, err ); 00127 * bool have_midedge = !!(ho & 1<<1); 00128 * bool have_midface = !!(ho & 1<<2); 00129 * bool have_midvol = !!(ho & 1<<3); 00130 *\endocde 00131 * 00132 * The advantange of this form of the function over the previous is 00133 * that a) it is possible to check for mid-nodes on sub-entities of 00134 * a varialbe dimension 'd': 00135 *\code 00136 * if (ho & (1<<d)) { ... } 00137 *\code 00138 * and b) it is convienent to test if an element has any higher-order 00139 * nodes: 00140 *\code 00141 * int ho = TopologyInfo::higher_order( topo, num_nodes, err ); 00142 * if (!ho) // if linear element 00143 * { ... } 00144 *\endocde 00145 */ 00146 static int higher_order( EntityTopology topo, unsigned num_nodes, MsqError& err ); 00147 00148 /**\brief Given a side, return index of mid-vertex for that side. 00149 * 00150 * Given a side specification (e.g. the first edge), return the 00151 * index of of the correponding mid-side node in the canoncial 00152 * ordering of the element connectivity. Returns -1 if the element 00153 * doesn't have the specified mid-side node. 00154 * 00155 *\param topo The element topology 00156 *\param num_nodes The number of nodes in the element type. 00157 *\param side_dimension The dimension of the side (e.g. 1 = edge, 2 = face) 00158 *\param side_number The number of the side (e.g. 0 for first edge/face, etc.) 00159 *\return Index (zero-based position) of higher-order node in canonical 00160 * ordering of element connectivity, or -1 of element type contains 00161 * no such node. 00162 */ 00163 static int higher_order_from_side( EntityTopology topo, unsigned num_nodes, unsigned side_dimension, 00164 unsigned side_number, MsqError& err ); 00165 00166 /**\brief Get side given a higher-order node */ 00167 static void side_from_higher_order( EntityTopology topo, unsigned num_nodes, unsigned node_number, 00168 unsigned& side_dim_out, unsigned& side_num_out, MsqError& err ); 00169 00170 /** Get logical position given an element type node node index*/ 00171 static inline Sample sample_from_node( EntityTopology topo, unsigned num_nodes, unsigned node_number, 00172 MsqError& err ) 00173 { 00174 unsigned dim, num; 00175 side_from_higher_order( topo, num_nodes, node_number, dim, num, err ); 00176 return Sample( dim, num ); 00177 } 00178 /** Get node index from logical position */ 00179 static inline int node_from_sample( EntityTopology topo, unsigned num_nodes, Sample sample, MsqError& err ) 00180 { 00181 return higher_order_from_side( topo, num_nodes, sample.dimension, sample.number, err ); 00182 } 00183 /**\brief Get indices of edge ends in element connectivity array 00184 * 00185 * Given an edge number in (0,edges(type)], return which positions 00186 * in the connectivity list for the element type correspond to the 00187 * end vertices of that edge. 00188 */ 00189 static const unsigned* edge_vertices( EntityTopology topo, unsigned edge_number, MsqError& err ); 00190 static const unsigned* edge_vertices( EntityTopology topo, unsigned edge_number ); 00191 00192 /**\brief Get face corner indices in element connectivity array 00193 * 00194 * Given an face number in (0,faces(type)], return which positions 00195 * in the connectivity list for the element type correspond to the 00196 * vertices of that face, ordered in a counter-clockwise cycle 00197 * around a vector pointing out of the element for an ideal element. 00198 */ 00199 static const unsigned* face_vertices( EntityTopology topo, unsigned face_number, unsigned& num_vertices_out, 00200 MsqError& err ); 00201 static const unsigned* face_vertices( EntityTopology topo, unsigned face_number, unsigned& num_vertices_out ); 00202 00203 /**\brief Get corner indices of side 00204 * 00205 * Get the indices into element connectivity list for the 00206 * corners/ends of the specified side of the element. 00207 * edge_vertices() and face_vertices() are special cases 00208 * of this method. 00209 * 00210 * If the passed dimension equals that of the specified topology, 00211 * the side number is ignored and all the corners of the 00212 * element are returned. Fails if side dimension 00213 * greater than the dimension of the specified topology type. 00214 */ 00215 static const unsigned* side_vertices( EntityTopology topo, unsigned side_dimension, unsigned side_number, 00216 unsigned& num_verts_out, MsqError& err ); 00217 static const unsigned* side_vertices( EntityTopology topo, unsigned side_dimension, unsigned side_number, 00218 unsigned& num_verts_out ); 00219 00220 /**\brief Return which side the specified mid-node lies on 00221 * 00222 * Given an non-linear element type (specified by the 00223 * topology and length of the connectiivty array) and the 00224 * index of a node in the element's connectivity array, 00225 * return the lower-dimension entity (side) of the element 00226 * the mid-node lies on. 00227 * 00228 *\param topo Element topology 00229 *\param connectivity_length Number of nodes in element 00230 *\param node_index Which node of the element 00231 *\param side_dimension_out The dimension of the side containing the 00232 * midnode (0 = vertex, 1 = edge, 2 = face, 3 = volume) 00233 *\param side_number_out The canonical number of the side 00234 */ 00235 static void side_number( EntityTopology topo, unsigned connectivity_length, unsigned node_index, 00236 unsigned& side_dimension_out, unsigned& side_number_out, MsqError& err ); 00237 00238 /**\brief Get adjacent corner vertices 00239 * 00240 * Given the index of a vertex in an element, get the list of 00241 * indices corresponding to the adjacent corner vertices. 00242 * 00243 * Adjcent corner vertex indices are returned in the proper 00244 * order for constructing the active matrix for the corner. 00245 * 00246 * Given the array v of all vertices in the patch, the array v_i 00247 * containing the connectivity list for an element as 00248 * indices into v, and adj as the result of this function for some 00249 * corner of the element, the corresponding active matrix A for 00250 * that corner can be constructed as: 00251 * Matrix3D A; 00252 * A.set_column( 0, v[v_i[adj[0]]] - v[v_i[0]] ); 00253 * A.set_column( 1, v[v_i[adj[1]]] - v[v_i[0]] ); 00254 * A.set_column( 2, v[v_i[adj[2]]] - v[v_i[0]] ); 00255 * 00256 *\param topo The element type 00257 *\param index The index of a corner vertex 00258 *\param num_adj_out The number of adjacent vertices (output) 00259 *\return The array of vertex indices 00260 */ 00261 static const unsigned* adjacent_vertices( EntityTopology topo, unsigned index, unsigned& num_adj_out ); 00262 00263 /**\brief Get reverse adjacency offsets 00264 * 00265 * Get reverse mapping of results from adjacent_vertices(). 00266 * 00267 * Let i be the input vertex index. For each vertex index j 00268 * for which the result of adjacent_vertices() contains i, return 00269 * the offset into that result at which i would occur. The 00270 * results are returned in the same order as each j is returned 00271 * in the results of adjacent_vertices(...,i,...). Thus the 00272 * combination of the results of adjacent_vertices(...,i,...) 00273 * and this method provide a reverse mapping of the results of 00274 * adjacent_vertices(...,j,...) for i in all j. 00275 * 00276 * Given: 00277 * const unsigned *a, *b, *r; 00278 * unsigned n, nn, c = corners(type); 00279 * a = adjacent_vertices( type, i, n ); // for any i < c 00280 * r = reverse_vertex_adjacency_offsets( type, i, n ); 00281 * b = adjacent_vertices( type, a[k], nn ); // for any k < n 00282 * Then: 00283 * b[r[k]] == i 00284 */ 00285 static const unsigned* reverse_vertex_adjacency_offsets( EntityTopology topo, unsigned index, 00286 unsigned& num_idx_out ); 00287 00288 /**\brief Find which edge of an element has the passed vertex indices 00289 * 00290 * Find which edge of the element cooresponds to a list of positions 00291 * in the canonical element ordering. 00292 *\param topo The element type 00293 *\param edge_vertices The array of side vertex indices 00294 *\param reversed_out True if edge is reversed wrt edge_vertices 00295 *\return The edge number. 00296 */ 00297 static unsigned find_edge( EntityTopology topo, const unsigned* edge_vertices, bool& reversed_out, MsqError& err ); 00298 00299 /**\brief Find which face of an element has the passed vertex indices 00300 * 00301 * Find which face of the element cooresponds to a list of positions 00302 * in the canonical element ordering. 00303 *\param topo The element type 00304 *\param face_vertices The array of face vertex indices 00305 *\param num_face_vertices The length of face_vertices 00306 *\param reversed_out True if face is reversed wrt face_vertices 00307 *\return The face number. 00308 */ 00309 static unsigned find_face( EntityTopology topo, const unsigned* face_vertices, unsigned num_face_vertices, 00310 bool& reversed_out, MsqError& err ); 00311 00312 /**\brief Find which side of an element has the passed vertex indices 00313 * 00314 * Find which side of the element cooresponds to a list of positions 00315 * in the canonical element ordering. 00316 *\param topo The element type 00317 *\param side_vertices The array of side vertex indices 00318 *\param num_vertices The length of side_vertices 00319 *\param dimension_out The dimension of the side 00320 *\param number_out The enumerated index for the side 00321 *\param reversed_out True if side is reversed wrt side_vertices 00322 */ 00323 static void find_side( EntityTopology topo, const unsigned* side_vertices, unsigned num_vertices, 00324 unsigned& dimension_out, unsigned& number_out, bool& reversed_out, MsqError& err ); 00325 00326 /**\brief Test if two elements share lower-order topology 00327 * 00328 * Test if two elements share lower-order topology (e.g. 00329 * whether or not two tetrahedra share an edge.) 00330 * 00331 * That is compare the 'element_1_side_number'-th lower order 00332 * topology of dimension 'side_dimension' on element 1 with the 00333 * 'element_2_side_number'-th lower order topology of dimension 00334 *'side_dimension' on element 2 00335 * 00336 *\param element_1_vertices The connectivity of the first element 00337 *\param element_1_topology The type of the first element 00338 *\param element_1_side_number Which lower-order topology to compare 00339 *\param element_2_vertices The connectivity of the second element 00340 *\param element_2_topology The type of the second element 00341 *\param element_2_side_number Whcih lower-order topology to compare 00342 *\param side_dimension The dimension of the lower-order topology 00343 */ 00344 static bool compare_sides( const size_t* element_1_vertices, EntityTopology element_1_topology, 00345 unsigned element_1_side_number, const size_t* element_2_vertices, 00346 EntityTopology element_2_topology, unsigned element_2_side_number, 00347 unsigned side_dimension, MsqError& err ); 00348 00349 private: 00350 enum 00351 { 00352 MAX_CORNER = 8, 00353 MAX_EDGES = 12, 00354 MAX_FACES = 6, 00355 MAX_FACE_CONN = 5, 00356 MAX_VERT_ADJ = 4, 00357 FIRST_FACE = TRIANGLE, 00358 LAST_FACE = QUADRILATERAL, 00359 FIRST_VOL = TETRAHEDRON, 00360 LAST_VOL = PYRAMID 00361 }; 00362 00363 unsigned char dimMap[MIXED]; /**< Get dimension of entity given topology */ 00364 unsigned char adjMap[MIXED][4]; /**< Get number of adj entities of dimension 0, 1 and dimension 2 */ 00365 /** Vertex indices for element edges */ 00366 unsigned edgeMap[LAST_VOL - FIRST_FACE + 1][MAX_EDGES][2]; 00367 /** Vertex indices for element faces */ 00368 unsigned faceMap[LAST_VOL - FIRST_VOL + 1][MAX_FACES][MAX_FACE_CONN]; 00369 /** Vertex-Vertex adjacency map */ 00370 unsigned vertAdjMap[LAST_VOL - FIRST_FACE + 1][MAX_CORNER][MAX_VERT_ADJ + 1]; 00371 /** Reverse Vertex-Vertex adjacency index map */ 00372 unsigned revVertAdjIdx[LAST_VOL - FIRST_FACE + 1][MAX_CORNER][MAX_VERT_ADJ + 1]; 00373 00374 const char* longNames[MIXED + 1]; 00375 const char* shortNames[MIXED + 1]; 00376 00377 TopologyInfo(); 00378 00379 static TopologyInfo instance; 00380 }; 00381 00382 } // namespace MBMesquite 00383 00384 #endif