shards  Version of the Day
Shards_CellTopology.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Shards : Shared Discretization Tools
6 // Copyright 2008, 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Carter Edwards (hcedwar@sandia.gov),
39 // Pavel Bochev (pbboche@sandia.gov), or
40 // Denis Ridzal (dridzal@sandia.gov).
41 //
42 // ************************************************************************
43 //@HEADER
44 */
45 
46 #ifndef Shards_CellTopology_hpp
47 #define Shards_CellTopology_hpp
48 
49 #ifdef HAVE_SHARDS_DEBUG
50 #define SHARDS_REQUIRE( S ) S
51 #else
52 #define SHARDS_REQUIRE( S ) /* empty */
53 #endif
54 
55 #include <string>
56 #include <vector>
57 #include <Shards_CellTopologyData.h>
58 #include <Shards_BasicTopologies.hpp>
59 
60 namespace shards {
61 
66 /*------------------------------------------------------------------------*/
67 
68 class CellTopology ;
69 
71 //std::ostream & operator << ( std::ostream & , const CellTopologyData & );
72 
73 
75 std::ostream & operator << ( std::ostream & , const CellTopology & );
76 
77 
81 enum ECellType {
82  ALL_CELLS = 0,
83  STANDARD_CELL,
84  NONSTANDARD_CELL
85 };
86 
87 inline std::string ECellTypeToString(ECellType cellType) {
88  std::string retString;
89  switch(cellType){
90  case ALL_CELLS: retString = "All"; break;
91  case STANDARD_CELL: retString = "Standard"; break;
92  case NONSTANDARD_CELL: retString = "Nonstandard"; break;
93  default: retString = "Invalid Cell";
94  }
95  return retString;
96 }
97 
98 
102 enum ETopologyType {
103  ALL_TOPOLOGIES,
104  BASE_TOPOLOGY,
105  EXTENDED_TOPOLOGY
106 };
107 
108 inline std::string ETopologyTypeToString(ETopologyType topologyType) {
109  std::string retString;
110  switch(topologyType){
111  case ALL_TOPOLOGIES: retString = "All"; break;
112  case BASE_TOPOLOGY: retString = "Base"; break;
113  case EXTENDED_TOPOLOGY: retString = "Extended"; break;
114  default: retString = "Invalid Topology";
115  }
116  return retString;
117 }
118 
119 
128 void getTopologies(std::vector<shards::CellTopology>& topologies,
129  const unsigned cellDim = 4,
130  const ECellType cellType = ALL_CELLS,
131  const ETopologyType topologyType = ALL_TOPOLOGIES);
132 
133 
134 
141 int isPredefinedCell(const CellTopology & cell);
142 
143 
144 
145 /*------------------------------------------------------------------------*/
168 private:
169 
173  void requireCell() const ;
174 
175 
180  void requireDimension( const unsigned subcellDim ) const ;
181 
182 
188  void requireSubcell( const unsigned subcellDim ,
189  const unsigned subcellOrd ) const ;
190 
191 
198  void requireNodeMap( const unsigned subcellDim ,
199  const unsigned subcellOrd ,
200  const unsigned nodeOrd ) const ;
201 
202  void requireNodePermutation( const unsigned permutationOrd ,
203  const unsigned nodeOrd ) const ;
204 
205  const CellTopologyData * m_cell ;
206 
207 public:
208 
209  /*------------------------------------------------------------------*/
216  unsigned getDimension() const
217  {
218  SHARDS_REQUIRE( requireCell() );
219  return m_cell->dimension ;
220  }
221 
222 
228  unsigned getKey() const
229  {
230  SHARDS_REQUIRE( requireCell() );
231  return m_cell->key ;
232  }
233 
234 
240  unsigned getBaseKey() const
241  {
242  SHARDS_REQUIRE( requireCell() );
243  return m_cell->base->key ;
244  }
245 
246 
247 
253  const char* getName() const
254  {
255  SHARDS_REQUIRE( requireCell() );
256  return m_cell->name ;
257  }
258 
259 
263  const char* getBaseName() const
264  {
265  SHARDS_REQUIRE( requireCell() );
266  return m_cell->base->name ;
267  }
268 
269 
271  unsigned getNodeCount() const
272  {
273  SHARDS_REQUIRE( requireCell() );
274  return m_cell->node_count ;
275  }
276 
277 
279  unsigned getVertexCount() const
280  {
281  SHARDS_REQUIRE( requireCell() );
282  return m_cell->vertex_count ;
283  }
284 
285 
287  unsigned getEdgeCount() const
288  {
289  SHARDS_REQUIRE( requireCell() );
290  return m_cell->edge_count ;
291  }
292 
294  unsigned getFaceCount() const
295  {
296  SHARDS_REQUIRE( requireCell() );
297  return m_cell->dimension == 3 ? m_cell->side_count : 0 ;
298  }
299 
300 
302  unsigned getSideCount() const
303  {
304  SHARDS_REQUIRE( requireCell() );
305  return m_cell->side_count ;
306  }
307 
308 
310  bool isValid() const
311  { return m_cell != 0 ; }
312 
313 
316  { return m_cell ; }
317 
318 
321  {
322  SHARDS_REQUIRE( requireCell() );
323  return m_cell->base ;
324  }
325 
326 
332  const CellTopologyData * getCellTopologyData( const unsigned subcell_dim ,
333  const unsigned subcell_ord ) const
334  {
335  SHARDS_REQUIRE( requireCell() );
336  SHARDS_REQUIRE( requireDimension(subcell_dim) );
337  SHARDS_REQUIRE( requireSubcell(subcell_dim,subcell_ord) );
338  return m_cell->subcell[subcell_dim][subcell_ord].topology ;
339  }
340 
341 
347  const CellTopologyData * getBaseCellTopologyData( const unsigned subcell_dim ,
348  const unsigned subcell_ord ) const
349  {
350  return getCellTopologyData(subcell_dim,subcell_ord)->base ;
351  }
352 
353 
358  unsigned getKey( const unsigned subcell_dim ,
359  const unsigned subcell_ord ) const
360  {
361  return getCellTopologyData(subcell_dim,subcell_ord)->key ;
362  }
363 
364 
365 
370  const char * getName(const unsigned subcell_dim,
371  const unsigned subcell_ord) const
372  {
373  return getCellTopologyData(subcell_dim,subcell_ord) -> name;
374  }
375 
376 
381  unsigned getNodeCount( const unsigned subcell_dim ,
382  const unsigned subcell_ord ) const
383  {
384  return getCellTopologyData(subcell_dim,subcell_ord)->node_count ;
385  }
386 
387 
392  unsigned getVertexCount( const unsigned subcell_dim ,
393  const unsigned subcell_ord ) const
394  {
395  return getCellTopologyData(subcell_dim,subcell_ord)->vertex_count ;
396  }
397 
398 
403  unsigned getEdgeCount( const unsigned subcell_dim ,
404  const unsigned subcell_ord ) const
405  {
406  return getCellTopologyData(subcell_dim,subcell_ord)->edge_count ;
407  }
408 
409 
414  unsigned getSideCount( const unsigned subcell_dim ,
415  const unsigned subcell_ord ) const
416  {
417  return getCellTopologyData(subcell_dim,subcell_ord)->side_count ;
418  }
419 
420 
424  unsigned getSubcellCount( const unsigned subcell_dim ) const
425  {
426  SHARDS_REQUIRE( requireCell() );
427  SHARDS_REQUIRE( requireDimension(subcell_dim) );
428  return m_cell->subcell_count[subcell_dim] ;
429  }
430 
431 
436  bool getSubcellHomogeneity( const unsigned subcell_dim ) const
437  {
438  SHARDS_REQUIRE( requireCell() );
439  SHARDS_REQUIRE( requireDimension(subcell_dim) );
440  return 0 != m_cell->subcell_homogeneity[subcell_dim] ;
441  }
442 
443 
450  unsigned getNodeMap( const unsigned subcell_dim ,
451  const unsigned subcell_ord ,
452  const unsigned subcell_node_ord ) const
453  {
454  SHARDS_REQUIRE( requireCell() );
455  SHARDS_REQUIRE( requireDimension(subcell_dim) );
456  SHARDS_REQUIRE( requireSubcell(subcell_dim,subcell_ord) );
457  SHARDS_REQUIRE( requireNodeMap(subcell_dim,subcell_ord,subcell_node_ord));
458  return m_cell->subcell[subcell_dim][subcell_ord].node[subcell_node_ord];
459  }
460 
461 
463  unsigned getNodePermutationCount() const
464  {
465  SHARDS_REQUIRE(requireCell());
466  return m_cell->permutation_count ;
467  }
468 
473  unsigned getNodePermutation( const unsigned permutation_ord ,
474  const unsigned node_ord ) const
475  {
476  SHARDS_REQUIRE(requireCell());
477  SHARDS_REQUIRE(requireNodePermutation(permutation_ord,node_ord));
478  return m_cell->permutation[permutation_ord].node[node_ord];
479  }
480 
485  unsigned getNodePermutationPolarity( const unsigned permutation_ord ) const
486  {
487  SHARDS_REQUIRE(requireCell());
488  SHARDS_REQUIRE(requireNodePermutation(permutation_ord,0));
489  return m_cell->permutation[permutation_ord].polarity;
490  }
491 
496  unsigned getNodePermutationInverse( const unsigned permutation_ord ,
497  const unsigned node_ord ) const
498  {
499  SHARDS_REQUIRE(requireCell());
500  SHARDS_REQUIRE(requireNodePermutation(permutation_ord,node_ord));
501  return m_cell->permutation_inverse[permutation_ord].node[node_ord];
502  }
503 
506  /*------------------------------------------------------------------*/
521  : m_cell( cell )
522  {}
523 
524 
532  CellTopology( const std::string & name,
533  const unsigned nodeCount);
534 
535 
545  CellTopology( const std::string & name,
546  const unsigned vertex_count,
547  const unsigned node_count,
548  const std::vector< const CellTopologyData * > & edges ,
549  const std::vector< unsigned > & edge_node_map ,
550  const CellTopologyData * base = NULL );
551 
552 
564  CellTopology( const std::string & name,
565  const unsigned vertex_count,
566  const unsigned node_count,
567  const std::vector< const CellTopologyData * > & edges ,
568  const std::vector< unsigned > & edge_node_map ,
569  const std::vector< const CellTopologyData * > & faces ,
570  const std::vector< unsigned > & face_node_map ,
571  const CellTopologyData * base = NULL );
572 
573 
576 
578  CellTopology( const CellTopology& right );
579 
582 
585 
588 }; // class CellTopology
589 
590 /*------------------------------------------------------------------------*/
591 /* \brief Find the permutation from the expected nodes to the actual nodes,
592  *
593  * Find permutation 'p' such that:
594  * actual_node[j] == expected_node[ top.permutation[p].node[j] ]
595  * for all vertices.
596  */
597 template< typename id_type >
598 int findPermutation( const CellTopologyData & top ,
599  const id_type * const expected_node ,
600  const id_type * const actual_node )
601 {
602  const int nv = top.vertex_count ;
603  const int np = top.permutation_count ;
604  int p = 0 ;
605  for ( ; p < np ; ++p ) {
606  const unsigned * const perm_node = top.permutation[p].node ;
607  int j = 0 ;
608  for ( ; j < nv && actual_node[j] == expected_node[ perm_node[j] ] ; ++j );
609  if ( nv == j ) break ;
610  }
611  if ( np == p ) p = -1 ;
612  return p ;
613 }
614 
615 template< typename id_type >
616 int findPermutation( const CellTopology & top ,
617  const id_type * const expected_node ,
618  const id_type * const actual_node )
619 {
620  return findPermutation( * top.getCellTopologyData() , expected_node , actual_node );
621 }
622 
623 /*------------------------------------------------------------------------*/
633 void badCellTopologyKey( const unsigned dimension ,
634  const unsigned face_count ,
635  const unsigned edge_count ,
636  const unsigned vertex_count ,
637  const unsigned node_count );
638 
639 
648 inline
649 unsigned cellTopologyKey( const unsigned dimension ,
650  const unsigned face_count ,
651  const unsigned edge_count ,
652  const unsigned vertex_count ,
653  const unsigned node_count )
654 {
655  const bool bad = ( dimension >> 3 ) ||
656  ( face_count >> 6 ) ||
657  ( edge_count >> 6 ) ||
658  ( vertex_count >> 6 ) ||
659  ( node_count >> 10 );
660 
661  if ( bad ) {
662  badCellTopologyKey( dimension ,
663  face_count ,
664  edge_count ,
665  vertex_count ,
666  node_count );
667  }
668 
669  const unsigned key = ( dimension << 28 ) |
670  ( face_count << 22 ) |
671  ( edge_count << 16 ) |
672  ( vertex_count << 10 ) |
673  ( node_count ) ;
674 
675  return key ;
676 }
677 
678 inline
679 bool operator==(const CellTopology &left, const CellTopology &right)
680 {
681  return left.getCellTopologyData() == right.getCellTopologyData();
682 }
683 
684 inline
685 bool operator<(const CellTopology &left, const CellTopology &right)
686 {
687  return left.getCellTopologyData() < right.getCellTopologyData();
688 // FIXME: Should is be this?
689 // return left.getKey() < right.getKey();
690 }
691 
692 inline
693 bool operator!=(const CellTopology &left, const CellTopology &right) {
694  return !(left == right);
695 }
696 
697 
700 } // namespace shards
701 
702 #undef SHARDS_REQUIRE
703 
704 #endif // Shards_CellTopology_hpp
705 
Provide input checked access (in debug mode) to cell topology data and a procedure to create custom c...
const CellTopologyData * getCellTopologyData(const unsigned subcell_dim, const unsigned subcell_ord) const
Raw cell topology data for a subcell of the given dimension and ordinal.
unsigned getNodeCount(const unsigned subcell_dim, const unsigned subcell_ord) const
Node count of a subcell of the given dimension and ordinal.
unsigned getSideCount() const
Side boundary subcell count of this cell topology.
bool isValid() const
This cell's raw topology data.
const char * getBaseName() const
Unique name for this cell's base topology.
const CellTopologyData * getBaseCellTopologyData() const
This cell's base cell topology's raw topology data.
const CellTopologyData * getBaseCellTopologyData(const unsigned subcell_dim, const unsigned subcell_ord) const
Raw cell topology data for the base topology of a subcell of the given dimension and ordinal.
unsigned getBaseKey() const
Unique key for this cell's base topology; under certain subcell uniformity conditions.
unsigned getSideCount(const unsigned subcell_dim, const unsigned subcell_ord) const
Side count of a subcell of the given dimension and ordinal.
unsigned getSubcellCount(const unsigned subcell_dim) const
Subcell count of subcells of the given dimension.
unsigned getEdgeCount() const
Edge boundary subcell count of this cell topology.
unsigned getNodePermutationCount() const
Number of node permutations defined for this cell.
CellTopology(const std::string &name, const unsigned vertex_count, const unsigned node_count, const std::vector< const CellTopologyData * > &edges, const std::vector< unsigned > &edge_node_map, const CellTopologyData *base=NULL)
Construct custom 2-cell (polygon) from a list of edges. The default base topology is the specified cu...
~CellTopology()
Destructor.
CellTopology(const CellTopology &right)
Copy constructor.
unsigned getNodePermutationPolarity(const unsigned permutation_ord) const
Permutation of a cell's node ordinals.
unsigned getNodeCount() const
Node count of this cell topology.
unsigned getNodeMap(const unsigned subcell_dim, const unsigned subcell_ord, const unsigned subcell_node_ord) const
Mapping from a subcell's node ordinal to a node ordinal of this parent cell topology.
CellTopology & operator=(const CellTopology &right)
Assignment operator *this = right.
CellTopology(const std::string &name, const unsigned vertex_count, const unsigned node_count, const std::vector< const CellTopologyData * > &edges, const std::vector< unsigned > &edge_node_map, const std::vector< const CellTopologyData * > &faces, const std::vector< unsigned > &face_node_map, const CellTopologyData *base=NULL)
Construct custom 3-cell (polyhedron) from a list of edges and sides. The default base topology is the...
unsigned getKey(const unsigned subcell_dim, const unsigned subcell_ord) const
Key of a subcell of the given dimension and ordinal.
CellTopology()
Default constructor initializes to NULL.
unsigned getVertexCount(const unsigned subcell_dim, const unsigned subcell_ord) const
Vertex count of a subcell of the given dimension and ordinal.
CellTopology(const CellTopologyData *cell)
Wrapper for safe access to a raw cell topology data.
CellTopology(const std::string &name, const unsigned nodeCount)
Constructs custom 1-cell (line) with base topology Line<>. Example use: the statement.
bool getSubcellHomogeneity(const unsigned subcell_dim) const
Query if all subcells of the given dimension have the same cell topology.
const CellTopologyData * getCellTopologyData() const
This cell's raw topology data.
unsigned getNodePermutationInverse(const unsigned permutation_ord, const unsigned node_ord) const
Inverse permutation of a cell's node ordinals.
unsigned getKey() const
Unique key for this cell topology; under certain subcell uniformity conditions.
unsigned getFaceCount() const
Face boundary subcell count of this cell topology.
unsigned getDimension() const
Dimension of this cell topology.
unsigned getVertexCount() const
Vertex count of this cell topology.
const char * getName(const unsigned subcell_dim, const unsigned subcell_ord) const
Name of a subcell of the given dimension and ordinal.
unsigned getEdgeCount(const unsigned subcell_dim, const unsigned subcell_ord) const
Edge count of a subcell of the given dimension and ordinal.
unsigned getNodePermutation(const unsigned permutation_ord, const unsigned node_ord) const
Permutation of a cell's node ordinals.
const char * getName() const
Unique name for this cell topology;.
unsigned cellTopologyKey(const unsigned dimension, const unsigned face_count, const unsigned edge_count, const unsigned vertex_count, const unsigned node_count)
Generate integer key from topological dimensions.
std::ostream & operator<<(std::ostream &, const CellTopology &)
Overloaded << operator for CellTopologyData objects.
void badCellTopologyKey(const unsigned dimension, const unsigned face_count, const unsigned edge_count, const unsigned vertex_count, const unsigned node_count)
Generates detailed message if one or more input parameters are out of their admissible bounds.
void getTopologies(std::vector< shards::CellTopology > &topologies, const unsigned cellDim=4, const ECellType cellType=ALL_CELLS, const ETopologyType topologyType=ALL_TOPOLOGIES)
Returns an std::vector with all cell topologies that meet the specified selection flags.
int isPredefinedCell(const CellTopology &cell)
Checks if the cell topology is predefined in shards.
const struct CellTopologyData * topology
Subcell topology.
const unsigned * node
Subcell indexing of with respect to parent cell.
A simple 'C' struct of cell topology attributes.
const char * name
Intuitive name for this topology.
unsigned node_count
Number of nodes (a.k.a. subcells).
unsigned side_count
Number of sides (a.k.a. boundary subcells).
const struct CellTopologyData * base
Base, a.k.a. not-extended, version of this topology where vertex_count == node_count.
unsigned key
Unique key for this topology.
unsigned edge_count
Number of edges (a.k.a. boundary subcells).
unsigned vertex_count
Number of vertices.
unsigned permutation_count
Number of defined permutations.
unsigned subcell_homogeneity[4]
Flag if the subcells of a given dimension are homogeneous.
const struct CellTopologyData_Subcell * subcell[4]
Array of subcells of each dimension.
const struct CellTopologyData_Permutation * permutation
Array of node permutations.
unsigned dimension
Topological dimension.
unsigned subcell_count[4]
Number of subcells of each dimension.