MOAB: Mesh Oriented datABase  (version 5.2.1)
TopologyInfo.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines