MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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) [email protected] 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