MOAB: Mesh Oriented datABase  (version 5.3.1)
NodeSet.hpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2007 Sandia National Laboratories.  Developed at the
00005     University of Wisconsin--Madison under SNL contract number
00006     624796.  The U.S. Government and the University of Wisconsin
00007     retain certain rights to 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     (2009) kraftche@cae.wisc.edu
00024 
00025   ***************************************************************** */
00026 
00027 /** \file NodeSet.hpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #include "TopologyInfo.hpp"
00033 
00034 #ifndef MSQ_NODE_SET_HPP
00035 #define MSQ_NODE_SET_HPP
00036 
00037 #include "Mesquite.hpp"
00038 #include <cassert>
00039 #include <iosfwd>
00040 #include "Bits.hpp"
00041 #include "Sample.hpp"
00042 
00043 #ifdef _WIN32
00044 #pragma warning( 4 : 4715 )
00045 #endif
00046 
00047 namespace MBMesquite
00048 {
00049 
00050 /** Utility class for storing one boolean mark/flag for each node in an element */
00051 class MESQUITE_EXPORT NodeSet
00052 {
00053   public:
00054     typedef unsigned BitSet;
00055 
00056     //! Misc constants.  Only NUM_CORNER_BITS, NUM_EDGE_BITS, and
00057     //! NUM_REGION_BITS should be modified.  All other contants are
00058     //! a function of those three values and the size of the bit storage.
00059     // enum {
00060     static const BitSet NUM_TOTAL_BITS = 8 * sizeof( BitSet );
00061     static const BitSet MSB_POS        = NUM_TOTAL_BITS - 1;
00062     //! Maximum number of corner nodes.
00063     static const BitSet NUM_CORNER_BITS = 8;
00064     //! Maximum number of mid-edge nodes
00065     static const BitSet NUM_EDGE_BITS = 16;
00066     //! Maximum number of mid-volume nodes
00067     static const BitSet NUM_REGION_BITS = 1;
00068     //! Maximum number of mid-face nodes
00069     static const BitSet NUM_FACE_BITS = NUM_TOTAL_BITS - ( NUM_CORNER_BITS + NUM_EDGE_BITS + NUM_REGION_BITS );
00070 
00071     //! LSB of corner node storage
00072     static const BitSet CORNER_OFFSET = 0;
00073     //! LSB of mid-edgee storage
00074     static const BitSet EDGE_OFFSET = CORNER_OFFSET + NUM_CORNER_BITS;
00075     //! LSB of mid-face storage
00076     static const BitSet FACE_OFFSET = EDGE_OFFSET + NUM_EDGE_BITS;
00077     //! LSB of mid-region storage
00078     static const BitSet REGION_OFFSET = FACE_OFFSET + NUM_FACE_BITS;
00079 
00080     //! Bit mask for all non-corner bits
00081     static const BitSet MID_NODE_MASK = ( ~0u ) << NUM_CORNER_BITS;
00082     //! Bit mask for all corner bits
00083     static const BitSet CORNER_MASK = ~MID_NODE_MASK;
00084     //! Mid-region mask
00085     static const BitSet REGION_MASK = ~( ( ~0u ) >> NUM_REGION_BITS );
00086     //! Bit mask for all mid-edge nodes
00087     static const BitSet EDGE_MASK = ( MID_NODE_MASK << ( NUM_TOTAL_BITS - EDGE_OFFSET - NUM_EDGE_BITS ) ) >>
00088                                     ( NUM_TOTAL_BITS - EDGE_OFFSET - NUM_EDGE_BITS );
00089     //! Bit mask for all mid-face nodes
00090     static const BitSet FACE_MASK = ~( CORNER_MASK | EDGE_MASK | REGION_MASK );
00091     //};
00092 
00093   private:
00094     BitSet bits;  //!< The data, one bit for each possible node location
00095 
00096     //! Return a bool value indicating the state of the specified bit.
00097     inline bool bit_to_bool( unsigned num ) const
00098     {
00099         return static_cast< bool >( ( bits >> num ) & 1u );
00100     }
00101 
00102     //! Set the specified bit to 1
00103     inline void set_bit( unsigned num )
00104     {
00105         bits |= ( 1u << num );
00106     }
00107 
00108     inline void set_bits( unsigned start_bit, unsigned count )
00109     {
00110         bits |= ( ~( (BitSet)0 ) >> ( NUM_TOTAL_BITS - count ) ) << start_bit;
00111     }
00112 
00113     //! Clear the specified bit (set it to zero)
00114     inline void clear_bit( unsigned num )
00115     {
00116         bits &= ~( 1u << num );
00117     }
00118 
00119     //! Count the number of non-zero bits with less significance than
00120     //! the specified bit.  (Mask out all bits except those of before
00121     //! the specified position and then count the remaining bits.)
00122     unsigned num_before_bit( unsigned p_position ) const
00123     {
00124         return popcount( bits & ~( ( ~0u ) << p_position ) );
00125     }
00126 
00127   public:
00128     NodeSet() : bits( 0u ) {}
00129 
00130     //! Clear all values
00131     void clear()
00132     {
00133         bits = 0u;
00134     }
00135 
00136     //! Set all marks/flags
00137     inline void set_all_nodes( EntityTopology type );
00138 
00139     //! Number of marked/flagged nodes
00140     unsigned num_nodes() const
00141     {
00142         return popcount( bits );
00143     }
00144 
00145     //! Check if any mid-nodes (higher-order nodes) are flaged
00146     BitSet have_any_mid_node() const
00147     {
00148         return bits & MID_NODE_MASK;
00149     }
00150     //! Check if any corner nodes are present
00151     BitSet have_any_corner_node() const
00152     {
00153         return bits & CORNER_MASK;
00154     }
00155     //! Check if any mid-edge nodes are present
00156     BitSet have_any_mid_edge_node() const
00157     {
00158         return bits & EDGE_MASK;
00159     }
00160     //! Check if any mid-face nodes are present
00161     BitSet have_any_mid_face_node() const
00162     {
00163         return bits & FACE_MASK;
00164     }
00165     //! Check if any mid-region nodes are present
00166     BitSet have_any_mid_region_node() const
00167     {
00168         return bits & REGION_MASK;
00169     }
00170 
00171     //! Position of a corner node in the list
00172     static unsigned corner_node_position( unsigned num )
00173     {
00174         assert( num < NUM_CORNER_BITS );
00175         return num + CORNER_OFFSET;
00176     }
00177     //! Position of a mid-edge node in the list
00178     static unsigned mid_edge_node_position( unsigned num )
00179     {
00180         assert( num < NUM_EDGE_BITS );
00181         return num + EDGE_OFFSET;
00182     }
00183     //! Position of a mid-face node in the list
00184     static unsigned mid_face_node_position( unsigned num )
00185     {
00186         assert( num < NUM_FACE_BITS );
00187         return num + FACE_OFFSET;
00188     }
00189     //! Position of a mid-region node in the list
00190     static unsigned mid_region_node_position( unsigned num = 0 )
00191     {
00192         assert( num < NUM_REGION_BITS );
00193         return num + REGION_OFFSET;
00194     }
00195     //! Position of a node in the list
00196     static unsigned position( Sample sample )
00197     {
00198         switch( sample.dimension )
00199         {
00200             case 0:
00201                 return corner_node_position( sample.number );
00202             case 1:
00203                 return mid_edge_node_position( sample.number );
00204             case 2:
00205                 return mid_face_node_position( sample.number );
00206             case 3:
00207                 return mid_region_node_position( sample.number );
00208         }
00209         assert( 0 );
00210         return ~0u;
00211     }
00212 
00213     //! Mark/flag corner node
00214     void set_corner_node( unsigned num )
00215     {
00216         set_bit( corner_node_position( num ) );
00217     }
00218     //! Mark/flag mid-edge node
00219     void set_mid_edge_node( unsigned num )
00220     {
00221         set_bit( mid_edge_node_position( num ) );
00222     }
00223     //! Mark/flag mid-face node
00224     void set_mid_face_node( unsigned num )
00225     {
00226         set_bit( mid_face_node_position( num ) );
00227     }
00228     //! Mark/flag mid-region node
00229     void set_mid_region_node( unsigned num = 0 )
00230     {
00231         set_bit( mid_region_node_position( num ) );
00232     }
00233     //! Mark/flag node
00234     void set_node( Sample sample )
00235     {
00236         switch( sample.dimension )
00237         {
00238             case 0:
00239                 set_corner_node( sample.number );
00240                 break;
00241             case 1:
00242                 set_mid_edge_node( sample.number );
00243                 break;
00244             case 2:
00245                 set_mid_face_node( sample.number );
00246                 break;
00247             case 3:
00248                 set_mid_region_node( sample.number );
00249                 break;
00250             default:
00251                 assert( 0 );
00252         }
00253     }
00254 
00255     //! un-mark (clear flag for) corner node
00256     void clear_corner_node( unsigned num )
00257     {
00258         clear_bit( corner_node_position( num ) );
00259     }
00260     //! un-mark (clear flag for) mid-edge node
00261     void clear_mid_edge_node( unsigned num )
00262     {
00263         clear_bit( mid_edge_node_position( num ) );
00264     }
00265     //! un-mark (clear flag for) mid-face node
00266     void clear_mid_face_node( unsigned num )
00267     {
00268         clear_bit( mid_face_node_position( num ) );
00269     }
00270     //! un-mark (clear flag for) mid-region node
00271     void clear_mid_region_node( unsigned num = 0 )
00272     {
00273         clear_bit( mid_region_node_position( num ) );
00274     }
00275     //! un-mark (clear flag for) node
00276     void clear_node( Sample sample )
00277     {
00278         switch( sample.dimension )
00279         {
00280             case 0:
00281                 clear_corner_node( sample.number );
00282                 break;
00283             case 1:
00284                 clear_mid_edge_node( sample.number );
00285                 break;
00286             case 2:
00287                 clear_mid_face_node( sample.number );
00288                 break;
00289             case 3:
00290                 clear_mid_region_node( sample.number );
00291                 break;
00292             default:
00293                 assert( 0 );
00294         }
00295     }
00296 
00297     //! Get mark/flag for corner node
00298     bool corner_node( unsigned num ) const
00299     {
00300         return bit_to_bool( corner_node_position( num ) );
00301     }
00302     //! Get mark/flag for mid-edge node
00303     bool mid_edge_node( unsigned num ) const
00304     {
00305         return bit_to_bool( mid_edge_node_position( num ) );
00306     }
00307     //! Test if two mid-edge nodes are both present
00308     bool both_edge_nodes( unsigned num1, unsigned num2 ) const
00309     {
00310         BitSet b = ( 1 << mid_edge_node_position( num1 ) ) | ( 1 << mid_edge_node_position( num2 ) );
00311         return ( bits & b ) == b;
00312     }
00313     //! Get mark/flag for mid-face node
00314     bool mid_face_node( unsigned num ) const
00315     {
00316         return bit_to_bool( mid_face_node_position( num ) );
00317     }
00318     //! Get mark/flag for mid-region node
00319     bool mid_region_node( unsigned num = 0 ) const
00320     {
00321         return bit_to_bool( mid_region_node_position( num ) );
00322     }
00323     //! Get mark/flag for node
00324     bool node( Sample sample ) const
00325     {
00326         switch( sample.dimension )
00327         {
00328             case 0:
00329                 return corner_node( sample.number );
00330                 break;
00331             case 1:
00332                 return mid_edge_node( sample.number );
00333                 break;
00334             case 2:
00335                 return mid_face_node( sample.number );
00336                 break;
00337             case 3:
00338                 return mid_region_node( sample.number );
00339                 break;
00340             default:
00341                 assert( 0 );
00342                 return false;
00343         }
00344     }
00345 
00346     //! Set all corner nodes
00347     inline void set_all_corner_nodes( EntityTopology type );
00348     //! Set all mid-edge nodes
00349     inline void set_all_mid_edge_nodes( EntityTopology type );
00350     //! Set all mid-face nodes
00351     inline void set_all_mid_face_nodes( EntityTopology type );
00352     //! Set all mid-region nodes
00353     inline void set_all_mid_region_nodes( EntityTopology type );
00354 
00355     //! Clear all mid-nodes
00356     void clear_all_mid_nodes()
00357     {
00358         bits &= ~MID_NODE_MASK;
00359     }
00360     //! Clear all corner nodes
00361     void clear_all_corner_nodes()
00362     {
00363         bits &= ~CORNER_MASK;
00364     }
00365     //! Clear all mid-edge nodes
00366     void clear_all_mid_edge_nodes()
00367     {
00368         bits &= ~EDGE_MASK;
00369     }
00370     //! Clear all mid-face nodes
00371     void clear_all_mid_face_nodes()
00372     {
00373         bits &= ~FACE_MASK;
00374     }
00375     //! Clear all mid-region nodes
00376     void clear_all_mid_region_nodes()
00377     {
00378         bits &= ~REGION_MASK;
00379     }
00380 
00381     //! Get number of marked/flagged nodes preceeding a specified corner node in the list
00382     unsigned num_before_corner( unsigned num ) const
00383     {
00384         return num_before_bit( corner_node_position( num ) );
00385     }
00386     //! Get number of marked/flagged nodes preceeding a specified mid-edge node in the list
00387     unsigned num_before_mid_edge( unsigned num ) const
00388     {
00389         return num_before_bit( mid_edge_node_position( num ) );
00390     }
00391     //! Get number of marked/flagged nodes preceeding a specified mid-face node in the list
00392     unsigned num_before_mid_face( unsigned num ) const
00393     {
00394         return num_before_bit( mid_face_node_position( num ) );
00395     }
00396     //! Get number of marked/flagged nodes preceeding a specified mid-region node in the list
00397     unsigned num_before_mid_region( unsigned num ) const
00398     {
00399         return num_before_bit( mid_region_node_position( num ) );
00400     }
00401     //! Get number of marked/flagged nodes preceeding a specified node in the list
00402     unsigned num_before( Sample sample ) const
00403     {
00404         switch( sample.dimension )
00405         {
00406             case 0:
00407                 return num_before_corner( sample.number );
00408                 break;
00409             case 1:
00410                 return num_before_mid_edge( sample.number );
00411                 break;
00412             case 2:
00413                 return num_before_mid_face( sample.number );
00414                 break;
00415             case 3:
00416                 return num_before_mid_region( sample.number );
00417                 break;
00418             default:
00419                 assert( 0 );
00420                 return ~0u;
00421         }
00422     }
00423 
00424     unsigned get_bits() const
00425     {
00426         return bits;
00427     }
00428 };
00429 
00430 //! Print bits in reverse order (least-signficant to most-significant,
00431 //! or corner 0 to mid-region).
00432 std::ostream& operator<<( std::ostream& s, NodeSet set );
00433 
00434 //! Set all corner nodes
00435 void NodeSet::set_all_corner_nodes( EntityTopology p_type )
00436 {
00437     set_bits( CORNER_OFFSET, TopologyInfo::corners( p_type ) );
00438 }
00439 //! Set all mid-edge nodes
00440 void NodeSet::set_all_mid_edge_nodes( EntityTopology p_type )
00441 {
00442     set_bits( EDGE_OFFSET, TopologyInfo::edges( p_type ) );
00443 }
00444 //! Set all mid-face nodes
00445 void NodeSet::set_all_mid_face_nodes( EntityTopology p_type )
00446 {
00447     set_bits( FACE_OFFSET, TopologyInfo::faces( p_type ) );
00448 }
00449 //! Set all mid-region nodes
00450 void NodeSet::set_all_mid_region_nodes( EntityTopology )
00451 {
00452     set_mid_region_node();
00453 }
00454 
00455 void NodeSet::set_all_nodes( EntityTopology p_type )
00456 {
00457     switch( TopologyInfo::dimension( p_type ) )
00458     {
00459         case 3:
00460             set_mid_region_node();
00461         case 2:
00462             set_all_mid_face_nodes( p_type );
00463         case 1:
00464             set_all_mid_edge_nodes( p_type );
00465         case 0:
00466             set_all_corner_nodes( p_type );
00467     }
00468 }
00469 
00470 }  // namespace MBMesquite
00471 
00472 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines