1 /**
2  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3  * storing and accessing finite element mesh data.
4  *
5  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
6  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7  * retains certain rights in this software.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  */
15 
16 /**
17  * \class moab::CN
18  * \author Tim Tautges
19  * \date April 2004
20  *
21  * \brief Canonical numbering data and functions
22  * This class represents canonical ordering of finite-element meshes.
23  * Elements in the finite element "zoo" are represented.  Canonical numbering
24  * denotes the vertex, edge, and face numbers making up each kind of element,
25  * and the vertex numbers defining those entities.  Functions for evaluating
26  * adjacencies and other things based on vertex numbering are also provided.
27  * By default, this class defines a zero-based numbering system.
28  * For a complete description of this class, see the document "MOAB Canonical
29  * Numbering Conventions", Timothy J. Tautges, Sandia National Laboratories
30  * Report #SAND2004-xxxx.
31  */
32 #ifndef MOAB_CN_HPP
33 #define MOAB_CN_HPP
34 
35 #include <vector>
36 #include <algorithm>
37 #include <cassert>
38 
39 #include "moab/EntityType.hpp"
40 
41 namespace moab {
42 
43 enum {
44   //! the maximum number n-1 dimension adjacencies a element may have
45   MAX_SUB_ENTITIES = 12,
46   //! the maximum number of nodes an n-1 dimensional element may have
47   MAX_SUB_ENTITY_VERTICES = 9
48 };
49 
50 typedef std::pair<EntityType, EntityType> DimensionPair;
51 
52 class CN
53 {
54 private:
55 
56 //! entity names
57   static const char *entityTypeNames[];
58 
59 //! declare private constructor, since we don't want to create any of these
60   CN();
61 
62 //! the basis of the numbering system (normally 0 or 1, 0 by default)
63   static short int numberBasis;
64 
65 //! switch the basis
66   static void SwitchBasis(const int old_basis, const int new_basis);
67 
68   static short increasingInts[];
69 
70 public:
71 
72   enum { MAX_NODES_PER_ELEMENT = 27 };
73   enum { MID_EDGE_BIT   = 1<<1,
74          MID_FACE_BIT   = 1<<2,
75          MID_REGION_BIT = 1<<3 };
76 
77     //! enum used to specify operation type
78   enum {INTERSECT = 0, UNION};
79 
80     // each entity type has two ConnMap objects, holding information about the bounding
81     // edges and faces for each entity; see comment for mConnectivityMap
82     // (this struct not documented with Doxygen)
83   struct ConnMap
84   {
85       // Topological dimension of this entry
86     short int topo_dimension;
87 
88       // Number of sub-elements of this dimension
89     short int num_sub_elements;
90 
91       // Number of nodes in each sub-element of this dimension
92     short int num_corners_per_sub_element[MAX_SUB_ENTITIES];
93 
94       // Type of each sub-element
95     EntityType target_type[MAX_SUB_ENTITIES];
96 
97       // Connectivity of each of the sub-elements
98     short int conn[MAX_SUB_ENTITIES][MAX_SUB_ENTITY_VERTICES];
99   };
100 
101     // mConnectivityMap[i=entity type][j=0,1,2]:
102     //  num_sub_elements = # bounding edges(j=0) or faces(j=1) for entity type i, or self (j=2)
103     //  num_corners_per_sub_element[k] (k=0..num_sub_elements-1) = number of nodes in sub-facet k
104     //    (can vary over sub-facets, e.g. faces bounding a pyramid) or self (j=2)
105     //  target_type[k] = entity type of sub-facet k (e.g. MBTRI or MBQUAD bounding a pyramid) or self (j=2)
106     //  conn[k][l] (l=0..CN::VerticesPerEntity[target_type[k]]) = vertex connectivity of sub-facet k,
107     //    with respect to entity i's canonical vertex ordering, or self (j=2)
108     // (not documented with Doxygen)
109   static const ConnMap mConnectivityMap[MBMAXTYPE][3];
110 
111     // structure used to define reverse canonical ordering information
112     // (not documented with Doxygen)
113   struct UpConnMap
114   {
115       // Number of higher-dimensional entities using each sub-entity
116     short int num_targets_per_source_element[MAX_SUB_ENTITIES];
117 
118       // Higher-dimensional entities using each sub-entity
119     short int targets_per_source_element[MAX_SUB_ENTITIES][MAX_SUB_ENTITIES];
120   };
121 
122     // Reverse canonical numbering, duplicates data in mConnectivityMap, but
123     // connectivity data in this table must be in ascending order (used for
124     // efficient sorting)
125     // (not documented with Doxygen)
126   static const UpConnMap mUpConnMap[MBMAXTYPE][4][4];
127 
128     // Mid-node bits indexed by number of nodes in element
129   static const unsigned char midNodesPerType[MBMAXTYPE][MAX_NODES_PER_ELEMENT+1];
130 
131     //! Permutation and reverse permutation vectors
132   static short int permuteVec[MBMAXTYPE][3][MAX_SUB_ENTITIES+1];
133   static short int revPermuteVec[MBMAXTYPE][3][MAX_SUB_ENTITIES+1];
134 
135   //! this const vector defines the starting and ending EntityType for
136   //! each dimension, e.g. TypeDimensionMap[2] returns a pair of EntityTypes
137   //! bounding dimension 2.
138   static const DimensionPair TypeDimensionMap[];
139 
140   //! get the basis of the numbering system
141   static short int GetBasis();
142 
143   //! set the basis of the numbering system
144   static void SetBasis(const int in_basis);
145 
146   //! return the string type name for this type
147   static inline
148   const char *EntityTypeName(const EntityType this_type);
149 
150   //! given a name, find the corresponding entity type
151   static EntityType EntityTypeFromName(const char *name);
152 
153   //! return the topological entity dimension
154   static inline
155   short int Dimension(const EntityType t);
156 
157   //! return the number of (corner) vertices contained in the specified type.
158   static inline
159   short int VerticesPerEntity(const EntityType t);
160 
161   //! return the number of sub-entities bounding the entity.
162   static inline
163   short int NumSubEntities(const EntityType t, const int d);
164 
165   //! return the type of a particular sub-entity.
166   //! \param this_type Type of entity for which sub-entity type is being queried
167   //! \param sub_dimension Topological dimension of sub-entity whose type is being queried
168   //! \param index Index of sub-entity whose type is being queried
169   //! \return type Entity type of sub-entity with specified dimension and index
170   static inline
171   EntityType SubEntityType(const EntityType this_type,
172                              const int sub_dimension,
173                              const int index);
174 
175   //! return the vertex indices of the specified sub-entity.
176   //! \param this_type Type of entity for which sub-entity connectivity is being queried
177   //! \param sub_dimension Dimension of sub-entity
178   //! \param sub_index Index of sub-entity
179   //! \param sub_entity_conn Connectivity of sub-entity (returned to calling function)
180   static inline
181   void SubEntityVertexIndices(const EntityType this_type,
182                               const int sub_dimension,
183                               const int sub_index,
184                               int sub_entity_conn[]);
185 
186   //! return the vertex indices of the specified sub-entity.
187   //! \param this_type Type of entity for which sub-entity connectivity is being queried
188   //! \param sub_dimension Dimension of sub-entity
189   //! \param sub_index Index of sub-entity
190   //! \param num_sub_ent_vertices the number of vertices in the sub-entity
191   static inline
192   const short* SubEntityVertexIndices( const EntityType this_type,
193                                        const int sub_dimension,
194                                        const int sub_index,
195                                        EntityType& sub_type,
196                                        int& num_sub_ent_vertices );
197 
198   //! return the node indices of the specified sub-entity.
199   //! \param this_topo            The topology of the queried element type
200   //! \param num_nodes            The number of nodes in the queried element type.
201   //! \param sub_dimension        Dimension of sub-entity
202   //! \param sub_index            Index of sub-entity
203   //! \param sub_entity_topo      (Output) Topology of requested sub-entity.
204   //! \param num_sub_entity_nodes (Output) Number of nodes in the requested sub-entity.
205   //! \param sub_entity_conn      (Output) Connectivity of sub-entity
206   static void SubEntityNodeIndices(const EntityType this_topo,
207                                    const int num_nodes,
208                                    const int sub_dimension,
209                                    const int sub_index,
210                                    EntityType& sub_entity_topo,
211                                    int& num_sub_entity_nodes,
212                                    int sub_entity_conn[]);
213 
214   //! return the vertices of the specified sub entity
215   //! \param parent_conn Connectivity of parent entity
216   //! \param parent_type Entity type of parent entity
217   //! \param sub_dimension Dimension of sub-entity being queried
218   //! \param sub_index Index of sub-entity being queried
219   //! \param sub_entity_conn Connectivity of sub-entity, based on parent_conn and canonical
220   //!           ordering for parent_type
221   //! \param num_sub_vertices Number of vertices in sub-entity
222   static void SubEntityConn(const void *parent_conn, const EntityType parent_type,
223                             const int sub_dimension,
224                             const int sub_index,
225                             void *sub_entity_conn, int &num_sub_vertices);
226 
227   //! For a specified set of sides of given dimension, return the intersection
228   //! or union of all sides of specified target dimension adjacent to those sides.
229   //! \param this_type Type of entity for which sub-entity connectivity is being queried
230   //! \param source_indices Indices of sides being queried
231   //! \param num_source_indices Number of entries in <em>source_indices</em>
232   //! \param source_dim Dimension of source entity
233   //! \param target_dim Dimension of target entity
234   //! \param index_list Indices of target entities (returned)
235   //! \param operation_type Specify either CN::INTERSECT or CN::UNION to get intersection
236   //!        or union of target entity lists over source entities
237   static short int AdjacentSubEntities(const EntityType this_type,
238                                  const int *source_indices,
239                                  const int num_source_indices,
240                                  const int source_dim,
241                                  const int target_dim,
242                                  std::vector<int> &index_list,
243                                  const int operation_type = CN::INTERSECT);
244 
245   //! return the side index represented in the input sub-entity connectivity in the input
246   //! parent entity connectivity array.
247   //! \param parent_conn Connectivity of parent entity being queried
248   //! \param parent_type Entity type of parent entity
249   //! \param child_conn Connectivity of child whose index is being queried
250   //! \param child_num_verts Number of vertices in <em>child_conn</em>
251   //! \param child_dim Dimension of child entity being queried
252   //! \param side_number Side number of child entity (returned)
253   //! \param sense Sense of child entity with respect to order in <em>child_conn</em> (returned)
254   //! \param offset Offset of <em>child_conn</em> with respect to canonical ordering data (returned)
255   //! \return status Returns zero if successful, -1 if not
256   static short int SideNumber(const EntityType parent_type, const int *parent_conn,
257                               const int *child_conn, const int child_num_verts,
258                               const int child_dim,
259                         int &side_number, int &sense, int &offset);
260   static short int SideNumber(const EntityType parent_type, const unsigned int *parent_conn,
261                         const unsigned int *child_conn, const int child_num_verts,
262                         const int child_dim,
263                         int &side_number, int &sense, int &offset);
264   static short int SideNumber(const EntityType parent_type, const long *parent_conn,
265                         const long *child_conn, const int child_num_verts,
266                         const int child_dim,
267                         int &side_number, int &sense, int &offset);
268   static short int SideNumber(const EntityType parent_type, const unsigned long *parent_conn,
269                         const unsigned long *child_conn, const int child_num_verts,
270                         const int child_dim,
271                         int &side_number, int &sense, int &offset);
272   static short int SideNumber(const EntityType parent_type, const unsigned long long *parent_conn,
273                               const unsigned long long *child_conn, const int child_num_verts,
274                               const int child_dim,
275                               int &side_number, int &sense, int &offset);
276   static short int SideNumber(const EntityType parent_type, void * const *parent_conn,
277                         void * const *child_conn, const int child_num_verts,
278                         const int child_dim,
279                         int &side_number, int &sense, int &offset);
280 
281   //! return the side index represented in the input sub-entity connectivity
282   //! \param parent_type Entity type of parent entity
283   //! \param child_conn_indices Child connectivity to query, specified as indices
284   //!                           into the connectivity list of the parent.
285   //! \param child_num_verts Number of values in <em>child_conn_indices</em>
286   //! \param child_dim Dimension of child entity being queried
287   //! \param side_number Side number of child entity (returned)
288   //! \param sense Sense of child entity with respect to order in <em>child_conn</em> (returned)
289   //! \param offset Offset of <em>child_conn</em> with respect to canonical ordering data (returned)
290   //! \return status Returns zero if successful, -1 if not
291   static short int SideNumber(const EntityType parent_type,
292                         const int *child_conn_indices, const int child_num_verts,
293                         const int child_dim,
294                         int &side_number, int &sense, int &offset);
295 
296   //! return the dimension and index of the opposite side, given parent entity type and child
297   //! dimension and index.  This function is only defined for certain types of parent/child types:
298   //! (Parent, Child dim->Opposite dim):
299   //!  (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0),
300   //!  (Tet, 2->0), (Tet, 1->1), (Tet, 0->2),
301   //!  (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element)
302   //! All other parent types and child dimensions return an error.
303   //!
304   //! \param parent_type The type of parent element
305   //! \param child_type The type of child element
306   //! \param child_index The index of the child element
307   //! \param opposite_index The index of the opposite element
308   //! \return status Returns 0 if successful, -1 if not
309   static short int OppositeSide(const EntityType parent_type,
310                           const int child_index,
311                           const int child_dim,
312                           int &opposite_index,
313                           int &opposite_dim);
314 
315   //! given two connectivity arrays, determine whether or not they represent the same entity.
316   //! \param conn1 Connectivity array of first entity
317   //! \param conn2 Connectivity array of second entity
318   //! \param num_vertices Number of entries in <em>conn1</em> and <em>conn2</em>
319   //! \param direct If positive, entities have the same sense (returned)
320   //! \param offset Offset of <em>conn2</em>'s first vertex in <em>conn1</em>
321   //! \return bool Returns true if <em>conn1</em> and <em>conn2</em> match
322   static bool ConnectivityMatch(const int *conn1,
323                                 const int *conn2,
324                                 const int num_vertices,
325                                 int &direct, int &offset);
326   static bool ConnectivityMatch(const unsigned int *conn1,
327                                 const unsigned int *conn2,
328                                 const int num_vertices,
329                                 int &direct, int &offset);
330   static bool ConnectivityMatch(const long* conn1,
331                                 const long* conn2,
332                                 const int num_vertices,
333                                 int& direct, int& offset );
334   static bool ConnectivityMatch(const unsigned long* conn1,
335                                 const unsigned long* conn2,
336                                 const int num_vertices,
337                                 int &direct, int& offset );
338   static bool ConnectivityMatch(const unsigned long long* conn1,
339                                 const unsigned long long* conn2,
340                                 const int num_vertices,
341                                 int &direct, int& offset );
342   static bool ConnectivityMatch(void* const* conn1,
343                                 void* const* conn2,
344                                 const int num_vertices,
345                                 int& direct, int& offset );
346 
347     //! Set permutation or reverse permutation vector
348     //! Forward permutation is from CN's numbering into application's ordering;
349     //! that is, if i is CN's index, pvec[i] is application's index.  This
350     //! function stores the permutation vector for this type and facet dimension,
351     //! which then is used in calls to permuteThis or revPermuteThis.
352     //! \param t EntityType for which to set permutation
353     //! \param dim Dimension of facets whose permutation array is being set
354     //! \param pvec Permutation array
355     //! \param num_entries Number of indicies in permutation array
356     //! \param is_reverse Array is reverse permutation
357   static inline
358   void setPermutation(const EntityType t, const int dim, short int *pvec,
359                       const int num_entries, const bool is_reverse = false);
360 
361     //! Reset permutation or reverse permutation vector
362     //! \param t EntityType whose permutation vector is being reset
363     //! \param dim Dimension of facets being reset; if -1 is input, all dimensions are reset
364   static inline
365   void resetPermutation(const EntityType t, const int dim);
366 
367     //! Permute a handle array according to permutation vector set with setPermute;
368     //! permutation is done in-place
369     //! \param t EntityType of handles in pvec
370     //! \param dim Dimension of handles in pvec
371     //! \param pvec Handle array being permuted
372     //! \param indices_per_ent Number of indices per entity
373     //! \param num_entries Number of entities in pvec
374   static int permuteThis(const EntityType t, const int dim, int *pvec,
375                          const int indices_per_ent, const int num_entries);
376   static int permuteThis(const EntityType t, const int dim, unsigned int *pvec,
377                          const int indices_per_ent, const int num_entries);
378   static int permuteThis(const EntityType t, const int dim, long *pvec,
379                          const int indices_per_ent, const int num_entries);
380   static int permuteThis(const EntityType t, const int dim, void **pvec,
381                          const int indices_per_ent, const int num_entries);
382 
383     //! Reverse permute a handle array according to reverse permutation vector set with setPermute;
384     //! reverse permutation is done in-place
385     //! \param t EntityType of handles in pvec
386     //! \param dim Dimension of handles in pvec
387     //! \param pvec Handle array being reverse permuted
388     //! \param indices_per_ent Number of indices per entity
389     //! \param num_entries Number of entities in pvec
390   static int revPermuteThis(const EntityType t, const int dim, int *pvec,
391                             const int indices_per_ent, const int num_entries);
392   static int revPermuteThis(const EntityType t, const int dim, unsigned int *pvec,
393                             const int indices_per_ent, const int num_entries);
394   static int revPermuteThis(const EntityType t, const int dim, long *pvec,
395                             const int indices_per_ent, const int num_entries);
396   static int revPermuteThis(const EntityType t, const int dim, void **pvec,
397                             const int indices_per_ent, const int num_entries);
398 
399   //! true if entities of a given type and number of nodes indicates mid edge nodes are present.
400   //! \param this_type Type of entity for which sub-entity connectivity is being queried
401   //! \param num_verts Number of nodes defining entity
402   //! \return bool Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates
403   //!  mid-edge nodes are likely
404   static inline
405   bool HasMidEdgeNodes(const EntityType this_type,
406                        const int num_verts);
407 
408   //! true if entities of a given type and number of nodes indicates mid face nodes are present.
409   //! \param this_type Type of entity for which sub-entity connectivity is being queried
410   //! \param num_verts Number of nodes defining entity
411   //! \return bool Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates
412   //!  mid-face nodes are likely
413   static inline
414   bool HasMidFaceNodes(const EntityType this_type,
415                        const int num_verts);
416 
417   //! true if entities of a given type and number of nodes indicates mid region nodes are present.
418   //! \param this_type Type of entity for which sub-entity connectivity is being queried
419   //! \param num_verts Number of nodes defining entity
420   //! \return bool Returns true if <em>this_type</em> combined with <em>num_nodes</em> indicates
421   //!  mid-region nodes are likely
422   static inline
423   bool HasMidRegionNodes(const EntityType this_type,
424                          const int num_verts);
425 
426   //! true if entities of a given type and number of nodes indicates mid edge/face/region nodes
427   //! are present.
428   //! \param this_type Type of entity for which sub-entity connectivity is being queried
429   //! \param num_verts Number of nodes defining entity
430   //! \param mid_nodes If <em>mid_nodes[i], i=1..2</em> is non-zero, indicates that mid-edge
431   //!    (i=1), mid-face (i=2), and/or mid-region (i=3) nodes are likely
432   static inline
433   void HasMidNodes(const EntityType this_type,
434                    const int num_verts,
435                    int mid_nodes[4]);
436 
437   //! Same as above, except returns a single integer with the bits, from
438   //! least significant to most significant set to one if the corresponding
439   //! mid nodes on sub entities of the least dimension (0) to the highest
440   //! dimension (3) are present in the elment type.
441   static inline
442   int HasMidNodes( const EntityType this_type, const int num_verts );
443 
444   //! given data about an element and a vertex in that element, return the dimension
445   //! and index of the sub-entity that the vertex resolves.  If it does not resolve a
446   //! sub-entity, either because it's a corner node or it's not in the element, -1 is
447   //! returned in both return values.
448   //! \param elem_type Type of entity being queried
449   //! \param num_nodes The number of nodes in the element connectivity
450   //! \param ho_node_index The position of the HO node in the connectivity list (zero based)
451   //! \param parent_dim Dimension of sub-entity high-order node resolves (returned)
452   //! \param parent_index Index of sub-entity high-order node resolves (returned)
453   static void HONodeParent( EntityType elem_type,
454                             int num_nodes,
455                             int ho_node_index,
456                             int &parent_dim,
457                             int &parent_index );
458 
459   //! for an entity of this type with num_verts vertices, and a specified subfacet
460   //! (dimension and index), return the index of the higher order node for that entity
461   //! in this entity's connectivity array
462   //! \param this_type Type of entity being queried
463   //! \param num_verts Number of vertices for the entity being queried
464   //! \param subfacet_dim Dimension of sub-entity being queried
465   //! \param subfacet_index Index of sub-entity being queried
466   //! \return index Index of sub-entity's higher-order node
467   static short int HONodeIndex(const EntityType this_type, const int num_verts,
468                          const int subfacet_dim, const int subfacet_index);
469 };
470 
471   //! get the basis of the numbering system
GetBasis()472 inline short int CN::GetBasis() {return numberBasis;}
473 
EntityTypeName(const EntityType this_type)474 inline const char *CN::EntityTypeName(const EntityType this_type)
475 {
476   return entityTypeNames[this_type];
477 }
478 
Dimension(const EntityType t)479 inline short int CN::Dimension(const EntityType t)
480 {
481   return mConnectivityMap[t][0].topo_dimension;
482 }
483 
VerticesPerEntity(const EntityType t)484 inline short int CN::VerticesPerEntity(const EntityType t)
485 {
486   return (MBVERTEX == t ? (short int) 1 : mConnectivityMap[t][mConnectivityMap[t][0].topo_dimension-1].num_corners_per_sub_element[0]);
487 }
488 
NumSubEntities(const EntityType t,const int d)489 inline short int CN::NumSubEntities(const EntityType t, const int d)
490 {
491   return (t != MBVERTEX && d > 0 ? mConnectivityMap[t][d-1].num_sub_elements :
492           (d ? (short int) -1 : VerticesPerEntity(t)));
493 }
494 
495   //! return the type of a particular sub-entity.
SubEntityType(const EntityType this_type,const int sub_dimension,const int index)496 inline EntityType CN::SubEntityType(const EntityType this_type,
497                                         const int sub_dimension,
498                                         const int index)
499 {
500 
501   return (!sub_dimension ? MBVERTEX :
502           (Dimension(this_type) == sub_dimension && 0 == index ? this_type :
503           mConnectivityMap[this_type][sub_dimension-1].target_type[index]));
504 }
505 
SubEntityVertexIndices(const EntityType this_type,const int sub_dimension,const int index,EntityType & sub_type,int & n)506 inline const short* CN::SubEntityVertexIndices( const EntityType this_type,
507                                                   const int sub_dimension,
508                                                   const int index,
509                                                   EntityType& sub_type,
510                                                   int& n )
511 {
512   if (sub_dimension == 0) {
513     n = 1;
514     sub_type = MBVERTEX;
515     return increasingInts + index;
516   }
517   else {
518     const CN::ConnMap& map = mConnectivityMap[this_type][sub_dimension-1];
519     sub_type = map.target_type[index];
520     n = map.num_corners_per_sub_element[index];
521     return map.conn[index];
522   }
523 }
524 
525   //! return the connectivity of the specified sub-entity.
SubEntityVertexIndices(const EntityType this_type,const int sub_dimension,const int index,int sub_entity_conn[])526 inline void CN::SubEntityVertexIndices(const EntityType this_type,
527                                          const int sub_dimension,
528                                          const int index,
529                                          int sub_entity_conn[])
530 {
531   EntityType type;
532   int n;
533   const short* indices = SubEntityVertexIndices( this_type, sub_dimension, index, type, n );
534   std::copy( indices, indices+n, sub_entity_conn );
535 }
536 
HasMidEdgeNodes(const EntityType this_type,const int num_nodes)537 inline bool CN::HasMidEdgeNodes(const EntityType this_type,
538                                      const int num_nodes)
539 {
540   const int bits = HasMidNodes( this_type, num_nodes );
541   return static_cast<bool>( (bits & (1<<1)) >> 1 );
542 }
543 
HasMidFaceNodes(const EntityType this_type,const int num_nodes)544 inline bool CN::HasMidFaceNodes(const EntityType this_type,
545                                        const int num_nodes)
546 {
547   const int bits = HasMidNodes( this_type, num_nodes );
548   return static_cast<bool>( (bits & (1<<2)) >> 2 );
549 }
550 
HasMidRegionNodes(const EntityType this_type,const int num_nodes)551 inline bool CN::HasMidRegionNodes(const EntityType this_type,
552                                          const int num_nodes)
553 {
554   const int bits = HasMidNodes( this_type, num_nodes );
555   return static_cast<bool>( (bits & (1<<3)) >> 3 );
556 }
557 
HasMidNodes(const EntityType this_type,const int num_nodes)558 inline int CN::HasMidNodes( const EntityType this_type, const int num_nodes )
559 {
560   assert( (unsigned)num_nodes <= (unsigned)MAX_NODES_PER_ELEMENT );
561   return midNodesPerType[this_type][num_nodes];
562 }
563 
564 
HasMidNodes(const EntityType this_type,const int num_nodes,int mid_nodes[4])565 inline void CN::HasMidNodes(const EntityType this_type, const int num_nodes,
566                               int mid_nodes[4])
567 {
568   const int bits = HasMidNodes( this_type, num_nodes );
569   mid_nodes[0] = 0;
570   mid_nodes[1] = (bits & (1<<1)) >> 1;
571   mid_nodes[2] = (bits & (1<<2)) >> 2;
572   mid_nodes[3] = (bits & (1<<3)) >> 3;
573 }
574 
575 //! Set permutation or reverse permutation vector
setPermutation(const EntityType t,const int dim,short int * pvec,const int num_entries,const bool is_reverse)576 inline void CN::setPermutation(const EntityType t, const int dim, short int *pvec,
577                                  const int num_entries, const bool is_reverse)
578 {
579   short int *this_vec = permuteVec[t][dim], *that_vec = revPermuteVec[t][dim];
580   if (is_reverse) {
581     this_vec = revPermuteVec[t][dim];
582     that_vec = permuteVec[t][dim];
583   }
584 
585   for (short int i = 0; i < num_entries; i++) {
586     this_vec[i] = pvec[i];
587     that_vec[pvec[i]] = i;
588   }
589 
590   this_vec[MAX_SUB_ENTITIES] = that_vec[MAX_SUB_ENTITIES] = (short)num_entries;
591 }
592 
593 //! Reset permutation or reverse permutation vector
resetPermutation(const EntityType t,const int dim)594 inline void CN::resetPermutation(const EntityType t, const int dim)
595 {
596   if (-1 == dim) {
597     for (unsigned int i = 0; i < 3; i++) resetPermutation(t, i);
598     return;
599   }
600 
601   for (short unsigned int i = 0; i < MAX_SUB_ENTITIES; i++) {
602     revPermuteVec[t][dim][i] = permuteVec[t][dim][i] = i;
603   }
604 
605   revPermuteVec[t][dim][MAX_SUB_ENTITIES] =
606     permuteVec[t][dim][MAX_SUB_ENTITIES] = MAX_SUB_ENTITIES+1;
607 }
608 
609 } // namespace moab
610 
611 #endif
612