shards Version of the Day
Shards_CellTopology.hpp
00001 /*
00002 //@HEADER
00003 // ************************************************************************
00004 //
00005 //                Shards : Shared Discretization Tools
00006 //                 Copyright 2008 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 class CellTopologyPrivate ;
00070 
00072 //std::ostream & operator << ( std::ostream & , const CellTopologyData & );
00073 
00074 
00076 std::ostream & operator << ( std::ostream & , const CellTopology & );
00077 
00078 
00082 enum ECellType {
00083   ALL_CELLS = 0,
00084   STANDARD_CELL,
00085   NONSTANDARD_CELL
00086 };
00087 
00088 inline std::string ECellTypeToString(ECellType cellType) {
00089   std::string retString;
00090   switch(cellType){
00091     case ALL_CELLS:         retString = "All";           break;
00092     case STANDARD_CELL:     retString = "Standard";      break;
00093     case NONSTANDARD_CELL:  retString = "Nonstandard";   break;
00094     default:                retString = "Invalid Cell";
00095   }
00096   return retString;
00097 }
00098 
00099 
00103 enum ETopologyType {
00104   ALL_TOPOLOGIES,
00105   BASE_TOPOLOGY,
00106   EXTENDED_TOPOLOGY
00107 };
00108 
00109 inline std::string ETopologyTypeToString(ETopologyType topologyType) {
00110   std::string retString;
00111   switch(topologyType){
00112     case ALL_TOPOLOGIES:      retString = "All";            break;
00113     case BASE_TOPOLOGY:       retString = "Base";           break;
00114     case EXTENDED_TOPOLOGY:   retString = "Extended";       break;
00115     default:                  retString = "Invalid Topology";
00116   }
00117   return retString;
00118 }
00119 
00120 
00129 void getTopologies(std::vector<shards::CellTopology>& topologies,
00130                    const unsigned       cellDim   = 4,
00131                    const ECellType      cellType      = ALL_CELLS,
00132                    const ETopologyType  topologyType  = ALL_TOPOLOGIES);
00133 
00134 
00135 
00142 int isPredefinedCell(const CellTopology &  cell);
00143 
00144 
00145 
00146 /*------------------------------------------------------------------------*/
00168 class CellTopology {
00169 private:
00170   
00172   void deleteOwned();
00173 
00177   void requireCell() const ;
00178   
00179   
00184   void requireDimension( const unsigned subcellDim ) const ;
00185   
00186   
00192   void requireSubcell( const unsigned subcellDim ,
00193                        const unsigned subcellOrd ) const ;
00194   
00195   
00202   void requireNodeMap( const unsigned subcellDim ,
00203                        const unsigned subcellOrd ,
00204                        const unsigned nodeOrd ) const ;
00205 
00206   void requireNodePermutation( const unsigned permutationOrd ,
00207                                const unsigned nodeOrd ) const ;
00208   
00209   const CellTopologyData    * m_cell ;
00210         CellTopologyPrivate * m_owned ;
00211 
00212 public:
00213 
00214   /*------------------------------------------------------------------*/
00221   unsigned getDimension() const
00222     {
00223       SHARDS_REQUIRE( requireCell() );
00224       return m_cell->dimension ;
00225     }
00226   
00227         
00233   unsigned getKey() const
00234     {
00235       SHARDS_REQUIRE( requireCell() );
00236       return m_cell->key ;
00237     }
00238 
00239         
00245   unsigned getBaseKey() const
00246     {
00247       SHARDS_REQUIRE( requireCell() );
00248       return m_cell->base->key ;
00249     }
00250         
00251         
00252         
00258   const char* getName() const
00259     {
00260         SHARDS_REQUIRE( requireCell() );
00261         return m_cell->name ;
00262     }
00263 
00264         
00268   const char* getBaseName() const
00269     {
00270       SHARDS_REQUIRE( requireCell() );
00271       return m_cell->base->name ;
00272     }
00273         
00274         
00276   unsigned getNodeCount() const
00277     {
00278       SHARDS_REQUIRE( requireCell() );
00279       return m_cell->node_count ;
00280     }
00281   
00282         
00284   unsigned getVertexCount() const
00285     {
00286       SHARDS_REQUIRE( requireCell() );
00287       return m_cell->vertex_count ;
00288     }
00289   
00290         
00292   unsigned getEdgeCount() const
00293     {
00294       SHARDS_REQUIRE( requireCell() );
00295       return m_cell->edge_count ;
00296     }
00297   
00299   unsigned getFaceCount() const
00300     {
00301       SHARDS_REQUIRE( requireCell() );
00302       return m_cell->dimension == 3 ? m_cell->side_count : 0 ;
00303     }
00304   
00305         
00307   unsigned getSideCount() const
00308     {
00309       SHARDS_REQUIRE( requireCell() );
00310       return m_cell->side_count ;
00311     }
00312   
00313         
00315   const CellTopologyData * getTopology() const
00316     { return m_cell ; }
00317 
00318         
00320   const CellTopologyData * getBaseTopology() const
00321     {
00322       SHARDS_REQUIRE( requireCell() );
00323       return m_cell->base ;
00324     }
00325 
00326         
00332   const CellTopologyData * getTopology( 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 * getBaseTopology( const unsigned subcell_dim ,
00348                                             const unsigned subcell_ord ) const
00349     {
00350       return getTopology(subcell_dim,subcell_ord)->base ;
00351     }
00352 
00353         
00358   unsigned getKey( const unsigned subcell_dim ,
00359                    const unsigned subcell_ord ) const
00360     {
00361       return getTopology(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 getTopology(subcell_dim,subcell_ord) -> name;
00374     }
00375         
00376         
00381   unsigned getNodeCount( const unsigned subcell_dim ,
00382                          const unsigned subcell_ord ) const
00383     {
00384       return getTopology(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 getTopology(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 getTopology(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 getTopology(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 ), m_owned( NULL )
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.getTopology() , 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 
00679 
00682 } // namespace shards
00683 
00684 #undef SHARDS_REQUIRE
00685 
00686 #endif // Shards_CellTopology_hpp
00687 
 All Classes Functions Variables Typedefs Enumerator