MOAB: Mesh Oriented datABase  (version 5.4.0)
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,
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines