shards Version of the Day
Shards_CellTopology.hpp
00001 /*
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //                Shards : Shared Discretization Tools
00006 //                 Copyright 2008, 2011 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Carter Edwards (hcedwar@sandia.gov),
00039 //                    Pavel Bochev (pbboche@sandia.gov), or
00040 //                    Denis Ridzal (dridzal@sandia.gov).
00041 //
00042 // ************************************************************************
00043 //@HEADER
00044 */
00045 
00046 #ifndef Shards_CellTopology_hpp
00047 #define Shards_CellTopology_hpp
00048 
00049 #ifdef HAVE_SHARDS_DEBUG
00050 #define SHARDS_REQUIRE( S )  S
00051 #else
00052 #define SHARDS_REQUIRE( S ) /* empty */
00053 #endif
00054 
00055 #include <string>
00056 #include <vector>
00057 #include <Shards_CellTopologyData.h>
00058 #include <Shards_BasicTopologies.hpp>
00059 
00060 namespace shards {
00061 
00066 /*------------------------------------------------------------------------*/
00067 
00068 class CellTopology ;
00069 
00071 //std::ostream & operator << ( std::ostream & , const CellTopologyData & );
00072 
00073 
00075 std::ostream & operator << ( std::ostream & , const CellTopology & );
00076 
00077 
00081 enum ECellType {
00082   ALL_CELLS = 0,
00083   STANDARD_CELL,
00084   NONSTANDARD_CELL
00085 };
00086 
00087 inline std::string ECellTypeToString(ECellType cellType) {
00088   std::string retString;
00089   switch(cellType){
00090     case ALL_CELLS:         retString = "All";           break;
00091     case STANDARD_CELL:     retString = "Standard";      break;
00092     case NONSTANDARD_CELL:  retString = "Nonstandard";   break;
00093     default:                retString = "Invalid Cell";
00094   }
00095   return retString;
00096 }
00097 
00098 
00102 enum ETopologyType {
00103   ALL_TOPOLOGIES,
00104   BASE_TOPOLOGY,
00105   EXTENDED_TOPOLOGY
00106 };
00107 
00108 inline std::string ETopologyTypeToString(ETopologyType topologyType) {
00109   std::string retString;
00110   switch(topologyType){
00111     case ALL_TOPOLOGIES:      retString = "All";            break;
00112     case BASE_TOPOLOGY:       retString = "Base";           break;
00113     case EXTENDED_TOPOLOGY:   retString = "Extended";       break;
00114     default:                  retString = "Invalid Topology";
00115   }
00116   return retString;
00117 }
00118 
00119 
00128 void getTopologies(std::vector<shards::CellTopology>& topologies,
00129                    const unsigned       cellDim   = 4,
00130                    const ECellType      cellType      = ALL_CELLS,
00131                    const ETopologyType  topologyType  = ALL_TOPOLOGIES);
00132 
00133 
00134 
00141 int isPredefinedCell(const CellTopology &  cell);
00142 
00143 
00144 
00145 /*------------------------------------------------------------------------*/
00167 class CellTopology {
00168 private:
00169   
00173   void requireCell() const ;
00174   
00175   
00180   void requireDimension( const unsigned subcellDim ) const ;
00181   
00182   
00188   void requireSubcell( const unsigned subcellDim ,
00189                        const unsigned subcellOrd ) const ;
00190   
00191   
00198   void requireNodeMap( const unsigned subcellDim ,
00199                        const unsigned subcellOrd ,
00200                        const unsigned nodeOrd ) const ;
00201 
00202   void requireNodePermutation( const unsigned permutationOrd ,
00203                                const unsigned nodeOrd ) const ;
00204   
00205   const CellTopologyData    * m_cell ;
00206 
00207 public:
00208 
00209   /*------------------------------------------------------------------*/
00216   unsigned getDimension() const
00217     {
00218       SHARDS_REQUIRE( requireCell() );
00219       return m_cell->dimension ;
00220     }
00221   
00222         
00228   unsigned getKey() const
00229     {
00230       SHARDS_REQUIRE( requireCell() );
00231       return m_cell->key ;
00232     }
00233 
00234         
00240   unsigned getBaseKey() const
00241     {
00242       SHARDS_REQUIRE( requireCell() );
00243       return m_cell->base->key ;
00244     }
00245         
00246         
00247         
00253   const char* getName() const
00254     {
00255         SHARDS_REQUIRE( requireCell() );
00256         return m_cell->name ;
00257     }
00258 
00259         
00263   const char* getBaseName() const
00264     {
00265       SHARDS_REQUIRE( requireCell() );
00266       return m_cell->base->name ;
00267     }
00268         
00269         
00271   unsigned getNodeCount() const
00272     {
00273       SHARDS_REQUIRE( requireCell() );
00274       return m_cell->node_count ;
00275     }
00276   
00277         
00279   unsigned getVertexCount() const
00280     {
00281       SHARDS_REQUIRE( requireCell() );
00282       return m_cell->vertex_count ;
00283     }
00284   
00285         
00287   unsigned getEdgeCount() const
00288     {
00289       SHARDS_REQUIRE( requireCell() );
00290       return m_cell->edge_count ;
00291     }
00292   
00294   unsigned getFaceCount() const
00295     {
00296       SHARDS_REQUIRE( requireCell() );
00297       return m_cell->dimension == 3 ? m_cell->side_count : 0 ;
00298     }
00299   
00300         
00302   unsigned getSideCount() const
00303     {
00304       SHARDS_REQUIRE( requireCell() );
00305       return m_cell->side_count ;
00306     }
00307   
00308         
00310   bool isValid() const
00311     { return m_cell != 0 ; }
00312 
00313         
00315   const CellTopologyData * getCellTopologyData() const
00316     { return m_cell ; }
00317 
00318         
00320   const CellTopologyData * getBaseCellTopologyData() const
00321     {
00322       SHARDS_REQUIRE( requireCell() );
00323       return m_cell->base ;
00324     }
00325 
00326         
00332   const CellTopologyData * getCellTopologyData( const unsigned subcell_dim ,
00333                                                 const unsigned subcell_ord ) const
00334     {
00335       SHARDS_REQUIRE( requireCell() );
00336       SHARDS_REQUIRE( requireDimension(subcell_dim) );
00337       SHARDS_REQUIRE( requireSubcell(subcell_dim,subcell_ord) );
00338       return m_cell->subcell[subcell_dim][subcell_ord].topology ;
00339     }
00340 
00341         
00347   const CellTopologyData * getBaseCellTopologyData( const unsigned subcell_dim ,
00348                                                     const unsigned subcell_ord ) const
00349     {
00350       return getCellTopologyData(subcell_dim,subcell_ord)->base ;
00351     }
00352 
00353         
00358   unsigned getKey( const unsigned subcell_dim ,
00359                    const unsigned subcell_ord ) const
00360     {
00361       return getCellTopologyData(subcell_dim,subcell_ord)->key ;
00362     }
00363 
00364 
00365         
00370   const char * getName(const unsigned subcell_dim,   
00371                        const unsigned subcell_ord) const
00372     {
00373       return getCellTopologyData(subcell_dim,subcell_ord) -> name;
00374     }
00375         
00376         
00381   unsigned getNodeCount( const unsigned subcell_dim ,
00382                          const unsigned subcell_ord ) const
00383     {
00384       return getCellTopologyData(subcell_dim,subcell_ord)->node_count ;
00385     }
00386 
00387         
00392   unsigned getVertexCount( const unsigned subcell_dim ,
00393                            const unsigned subcell_ord ) const
00394     {
00395       return getCellTopologyData(subcell_dim,subcell_ord)->vertex_count ;
00396     }
00397 
00398         
00403   unsigned getEdgeCount( const unsigned subcell_dim ,
00404                          const unsigned subcell_ord ) const
00405     {
00406       return getCellTopologyData(subcell_dim,subcell_ord)->edge_count ;
00407     }
00408   
00409         
00414   unsigned getSideCount( const unsigned subcell_dim ,
00415                          const unsigned subcell_ord ) const
00416     {
00417       return getCellTopologyData(subcell_dim,subcell_ord)->side_count ;
00418     }
00419 
00420         
00424   unsigned getSubcellCount( const unsigned subcell_dim ) const
00425     {
00426       SHARDS_REQUIRE( requireCell() );
00427       SHARDS_REQUIRE( requireDimension(subcell_dim) );
00428       return m_cell->subcell_count[subcell_dim] ;
00429     }
00430   
00431         
00436   bool getSubcellHomogeneity( const unsigned subcell_dim ) const
00437     {
00438       SHARDS_REQUIRE( requireCell() );
00439       SHARDS_REQUIRE( requireDimension(subcell_dim) );
00440       return 0 != m_cell->subcell_homogeneity[subcell_dim] ;
00441     }
00442   
00443         
00450   unsigned getNodeMap( const unsigned  subcell_dim ,
00451                        const unsigned  subcell_ord ,
00452                        const unsigned  subcell_node_ord ) const
00453     {
00454       SHARDS_REQUIRE( requireCell() );
00455       SHARDS_REQUIRE( requireDimension(subcell_dim) );
00456       SHARDS_REQUIRE( requireSubcell(subcell_dim,subcell_ord) );
00457       SHARDS_REQUIRE( requireNodeMap(subcell_dim,subcell_ord,subcell_node_ord));
00458       return m_cell->subcell[subcell_dim][subcell_ord].node[subcell_node_ord];
00459     }
00460 
00461 
00463   unsigned getNodePermutationCount() const
00464     {
00465       SHARDS_REQUIRE(requireCell());
00466       return m_cell->permutation_count ;
00467     }
00468 
00473   unsigned getNodePermutation( const unsigned permutation_ord ,
00474                                const unsigned node_ord ) const
00475     {
00476       SHARDS_REQUIRE(requireCell());
00477       SHARDS_REQUIRE(requireNodePermutation(permutation_ord,node_ord));
00478       return m_cell->permutation[permutation_ord].node[node_ord];
00479     }
00480   
00485   unsigned getNodePermutationPolarity( const unsigned permutation_ord ) const
00486     {
00487       SHARDS_REQUIRE(requireCell());
00488       SHARDS_REQUIRE(requireNodePermutation(permutation_ord,0));
00489       return m_cell->permutation[permutation_ord].polarity;
00490     }
00491   
00496   unsigned getNodePermutationInverse( const unsigned permutation_ord ,
00497                                       const unsigned node_ord ) const
00498     {
00499       SHARDS_REQUIRE(requireCell());
00500       SHARDS_REQUIRE(requireNodePermutation(permutation_ord,node_ord));
00501       return m_cell->permutation_inverse[permutation_ord].node[node_ord];
00502     }
00503   
00506   /*------------------------------------------------------------------*/
00520   CellTopology( const CellTopologyData * cell )
00521     : m_cell( cell )
00522   {}
00523   
00524         
00532   CellTopology( const std::string & name,
00533                 const unsigned      nodeCount);
00534   
00535         
00545   CellTopology( const std::string                             & name,
00546                 const unsigned                                  vertex_count,
00547                 const unsigned                                  node_count,
00548                 const std::vector< const CellTopologyData * > & edges ,
00549                 const std::vector< unsigned >                 & edge_node_map ,
00550                 const CellTopologyData                        * base = NULL );
00551 
00552   
00564   CellTopology( const std::string                             & name,
00565                 const unsigned                                  vertex_count,
00566                 const unsigned                                  node_count,
00567                 const std::vector< const CellTopologyData * > & edges ,
00568                 const std::vector< unsigned >                 & edge_node_map ,
00569                 const std::vector< const CellTopologyData * > & faces ,
00570                 const std::vector< unsigned >                 & face_node_map ,
00571                 const CellTopologyData                        * base = NULL );
00572   
00573   
00575   CellTopology& operator = (const CellTopology& right);
00576 
00578   CellTopology( const CellTopology& right );
00579 
00581   CellTopology();
00582 
00584   ~CellTopology();
00585   
00588 }; // class CellTopology
00589 
00590 /*------------------------------------------------------------------------*/
00591 /* \brief  Find the permutation from the expected nodes to the actual nodes,
00592  *
00593  *  Find permutation 'p' such that:
00594  *    actual_node[j] == expected_node[ top.permutation[p].node[j] ]
00595  *  for all vertices.
00596  */
00597 template< typename id_type >
00598 int findPermutation( const CellTopologyData & top ,
00599                      const id_type * const expected_node ,
00600                      const id_type * const actual_node )
00601 {
00602   const int nv = top.vertex_count ;
00603   const int np = top.permutation_count ;
00604   int p = 0 ;
00605   for ( ; p < np ; ++p ) {
00606     const unsigned * const perm_node = top.permutation[p].node ;
00607     int j = 0 ;
00608     for ( ; j < nv && actual_node[j] == expected_node[ perm_node[j] ] ; ++j );
00609     if ( nv == j ) break ;
00610   }
00611   if ( np == p ) p = -1 ;
00612   return p ;
00613 }
00614 
00615 template< typename id_type >
00616 int findPermutation( const CellTopology & top ,
00617                      const id_type * const expected_node ,
00618                      const id_type * const actual_node )
00619 {
00620   return findPermutation( * top.getCellTopologyData() , expected_node , actual_node );
00621 }
00622 
00623 /*------------------------------------------------------------------------*/
00633 void badCellTopologyKey( const unsigned dimension ,
00634                          const unsigned face_count ,
00635                          const unsigned edge_count ,
00636                          const unsigned vertex_count ,
00637                          const unsigned node_count );
00638   
00639 
00648 inline
00649 unsigned cellTopologyKey( const unsigned dimension ,
00650                           const unsigned face_count ,
00651                           const unsigned edge_count ,
00652                           const unsigned vertex_count ,
00653                           const unsigned node_count )
00654 {
00655   const bool bad = ( dimension    >> 3 ) ||
00656                    ( face_count   >> 6 ) ||
00657                    ( edge_count   >> 6 ) ||
00658                    ( vertex_count >> 6 ) ||
00659                    ( node_count   >> 10 );
00660 
00661   if ( bad ) {
00662     badCellTopologyKey( dimension , 
00663                         face_count ,
00664                         edge_count , 
00665                         vertex_count , 
00666                         node_count );
00667   }
00668 
00669   const unsigned key = ( dimension    << 28  ) |
00670                        ( face_count   << 22  ) |
00671                        ( edge_count   << 16  ) |
00672                        ( vertex_count << 10  ) |
00673                        ( node_count          ) ;
00674 
00675   return key ;
00676 }
00677 
00678 inline
00679 bool operator==(const CellTopology &left, const CellTopology &right)
00680 {
00681   return left.getCellTopologyData() == right.getCellTopologyData();
00682 }
00683 
00684 inline
00685 bool operator<(const CellTopology &left, const CellTopology &right)
00686 {
00687   return left.getCellTopologyData() < right.getCellTopologyData();
00688 // FIXME: Should is be this?  
00689 //  return left.getKey() < right.getKey(); 
00690 }
00691 
00692 inline
00693 bool operator!=(const CellTopology &left, const CellTopology &right) {
00694   return !(left == right);
00695 }
00696 
00697 
00700 } // namespace shards
00701 
00702 #undef SHARDS_REQUIRE
00703 
00704 #endif // Shards_CellTopology_hpp
00705 
 All Classes Functions Variables Typedefs Enumerator