#include <element_tree.hpp>
Public Types | |
typedef _Entity_handles | Entity_handles |
typedef _Box | Box |
typedef _Moab | Moab |
typedef _Parametrizer | Parametrizer |
typedef Entity_handles::value_type | Entity_handle |
Public Member Functions | |
Element_tree (Entity_handles &_entities, Moab &_moab, Box &_bounding_box, Parametrizer &_entity_contains) | |
Element_tree (Self &s) | |
template<typename Vector , typename Result > | |
Result & | find (const Vector &point, Result &result) const |
Private Types | |
typedef Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer > | Self |
typedef std::pair< Box, Entity_handle > | Leaf_element |
typedef _element_tree::_Node< Entity_handles, std::vector< Leaf_element > > | Node |
typedef common_tree::_Element_data< Box, std::bitset< NUM_DIM *MAX_ITERATIONS *2 > > | Element_data |
typedef std::vector< Node > | Nodes |
typedef std::tr1::unordered_map< Entity_handle, Element_data > | Element_map |
typedef std::vector< typename Element_map::iterator > | Element_list |
typedef _element_tree::_Partition_data< Box > | Partition_data |
Private Member Functions | |
template<typename Iterator , typename Split_data > | |
void | compute_split (Iterator &begin, Iterator &end, Split_data &split_data, bool iteration=false) |
template<typename Split_data > | |
bool | update_split_line (Split_data &data) const |
template<typename Iterator , typename Split_data , typename Directions > | |
void | determine_split (Iterator &begin, Iterator &end, Split_data &data, const Directions &directions) |
template<typename Iterator , typename Node_index , typename Directions , typename Partition_data > | |
void | build_tree (Iterator begin, Iterator end, const Node_index node, const Directions &directions, Partition_data &_data, int &depth, const bool is_middle=false) |
template<typename Vector , typename Node_index , typename Result > | |
Result & | _find_point (const Vector &point, const Node_index &index, Result &result) const |
Private Attributes | |
const Entity_handles & | entity_handles_ |
Nodes | tree_ |
Moab & | moab |
Box | bounding_box |
Parametrizer | entity_contains |
Definition at line 231 of file element_tree.hpp.
typedef _Box moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Box |
Definition at line 237 of file element_tree.hpp.
|
private |
Definition at line 249 of file element_tree.hpp.
|
private |
Definition at line 253 of file element_tree.hpp.
|
private |
Definition at line 252 of file element_tree.hpp.
typedef Entity_handles::value_type moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Entity_handle |
Definition at line 240 of file element_tree.hpp.
typedef _Entity_handles moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Entity_handles |
Definition at line 236 of file element_tree.hpp.
|
private |
Definition at line 245 of file element_tree.hpp.
typedef _Moab moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Moab |
Definition at line 238 of file element_tree.hpp.
|
private |
Definition at line 246 of file element_tree.hpp.
|
private |
Definition at line 250 of file element_tree.hpp.
typedef _Parametrizer moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Parametrizer |
Definition at line 239 of file element_tree.hpp.
|
private |
Definition at line 254 of file element_tree.hpp.
|
private |
Definition at line 244 of file element_tree.hpp.
|
inline |
Definition at line 258 of file element_tree.hpp.
259 : entity_handles_( _entities ), tree_(), moab( _moab ), bounding_box( _bounding_box ),
260 entity_contains( _entity_contains )
261 {
262 tree_.reserve( _entities.size() );
263 Element_map element_map( _entities.size() );
264 Partition_data _data;
265 common_tree::construct_element_map( entity_handles_, element_map, _data.bounding_box, moab );
266 bounding_box = _data.bounding_box;
267 _bounding_box = bounding_box;
268 Element_list element_ordering( element_map.size() );
269 std::size_t index = 0;
270 for( typename Element_map::iterator i = element_map.begin(); i != element_map.end(); ++i, ++index )
271 {
272 element_ordering[index] = i;
273 }
274 // We only build nonempty trees
275 if( element_ordering.size() )
276 {
277 // initially all bits are set
278 std::bitset< 3 > directions( 7 );
279 tree_.push_back( Node() );
280 int depth = 0;
281 build_tree( element_ordering.begin(), element_ordering.end(), 0, directions, _data, depth );
282 std::cout << "depth: " << depth << std::endl;
283 }
284 }
References moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::bounding_box, moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::build_tree(), moab::common_tree::construct_element_map(), moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::entity_handles_, and moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::tree_.
|
inline |
Definition at line 287 of file element_tree.hpp.
288 : entity_handles_( s.entity_handles_ ), tree_( s.tree_ ), moab( s.moab ), bounding_box( s.bounding_box ) 289 { 290 }
|
inlineprivate |
Definition at line 543 of file element_tree.hpp.
544 {
545 typedef typename Node::Entities::const_iterator Entity_iterator;
546 typedef typename std::pair< bool, Vector > Return_type;
547 const Node& node = tree_[index];
548 if( node.leaf() )
549 {
550 // check each node
551 for( Entity_iterator i = node.entities.begin(); i != node.entities.end(); ++i )
552 {
553 if( common_tree::box_contains_point( i->first, point ) )
554 {
555 Return_type r = entity_contains( moab, i->second, point );
556 if( r.first )
557 {
558 result = std::make_pair( i->second, r.second );
559 }
560 return result;
561 }
562 }
563 return Result( 0, point );
564 }
565 if( point[node.dim] < node.left_line )
566 {
567 return _find_point( point, node.left_, result );
568 }
569 else if( point[node.dim] > node.right_line )
570 {
571 return _find_point( point, node.right_, result );
572 }
573 else
574 {
575 Entity_handle middle = _find_point( point, node.middle_, result );
576 if( middle != 0 )
577 {
578 return result;
579 }
580 if( point[node.dim] < node.split )
581 {
582 return _find_point( point, node.left_, result );
583 }
584 return _find_point( point, node.right_, result );
585 }
586 }
References moab::common_tree::box_contains_point(), moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::entity_contains, and moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::tree_.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::find().
|
inlineprivate |
Definition at line 470 of file element_tree.hpp.
477 {
478 std::size_t number_elements = std::distance( begin, end );
479 if( depth < MAX_DEPTH && number_elements > ELEMENTS_PER_LEAF && ( !is_middle || directions.any() ) )
480 {
481 determine_split( begin, end, _data, directions );
482 // count_sort( begin, end, _data);
483 std::sort( begin, end, _element_tree::Iterator_comparator< Iterator >() );
484 // update the tree
485 tree_[node] = _data;
486 Iterator middle_begin( begin + _data.left() );
487 Iterator middle_end( middle_begin + _data.middle() );
488 std::vector< int > depths( 3, depth );
489 // left subtree
490 if( _data.left() > 0 )
491 {
492 Partition_data data( _data );
493 tree_.push_back( Node() );
494 tree_[node].children[0] = tree_.size() - 1;
495 correct_bounding_box( _data, data.bounding_box, 0 );
496 Directions new_directions( directions );
497 const bool axis_is_very_small =
498 ( data.bounding_box.max[_data.dim] - data.bounding_box.min[_data.dim] < EPSILON );
499 new_directions.set( _data.dim, axis_is_very_small );
500 build_tree( begin, middle_begin, tree_[node].children[0], new_directions, data, ++depths[0],
501 is_middle );
502 }
503 // middle subtree
504 if( _data.middle() > 0 )
505 {
506 Partition_data data( _data );
507 tree_.push_back( Node() );
508 tree_[node].children[1] = tree_.size() - 1;
509 correct_bounding_box( _data, data.bounding_box, 1 );
510 // force the middle subtree to split
511 // in a different direction from this one
512 Directions new_directions( directions );
513 new_directions.flip( tree_[node].dim );
514 bool axis_is_very_small =
515 ( data.bounding_box.max[_data.dim] - data.bounding_box.min[_data.dim] < EPSILON );
516 new_directions.set( _data.dim, axis_is_very_small );
517 build_tree( middle_begin, middle_end, tree_[node].children[1], new_directions, data, ++depths[1],
518 true );
519 }
520 // right subtree
521 if( _data.right() > 0 )
522 {
523 Partition_data data( _data );
524 tree_.push_back( Node() );
525 tree_[node].children[2] = tree_.size() - 1;
526 correct_bounding_box( _data, data.bounding_box, 2 );
527 Directions new_directions( directions );
528 const bool axis_is_very_small =
529 ( data.bounding_box.max[_data.dim] - data.bounding_box.min[_data.dim] < EPSILON );
530 new_directions.set( _data.dim, axis_is_very_small );
531
532 build_tree( middle_end, end, tree_[node].children[2], directions, data, ++depths[2], is_middle );
533 }
534 depth = *std::max_element( depths.begin(), depths.end() );
535 }
536 if( tree_[node].leaf() )
537 {
538 common_tree::assign_entities( tree_[node].entities, begin, end );
539 }
540 }
References moab::common_tree::assign_entities(), children, moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::determine_split(), dim, ELEMENTS_PER_LEAF, entities, EPSILON, and moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::tree_.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Element_tree().
|
inlineprivate |
Definition at line 295 of file element_tree.hpp.
296 {
297 typedef typename Iterator::value_type::value_type Map_value_type;
298 typedef typename Map_value_type::second_type::second_type Bitset;
299 // we will update the left/right line
300 double& left_line = split_data.left_line;
301 double& right_line = split_data.right_line;
302 double& split = split_data.split;
303 const int& dim = split_data.dim;
304 #ifdef ELEMENT_TREE_DEBUG
305 std::cout << std::endl;
306 std::cout << "-------------------" << std::endl;
307 std::cout << "dim: " << dim << " split: " << split << std::endl;
308 std::cout << "bounding_box min: ";
309 print_vector( split_data.bounding_box.min );
310 std::cout << "bounding_box max: ";
311 print_vector( split_data.bounding_box.max );
312 #endif
313 // for each elt determine if left/middle/right
314 for( Iterator i = begin; i != end; ++i )
315 {
316 const Box& box = ( *i )->second.first;
317 Bitset& bits = ( *i )->second.second;
318 // will be 0 if on left, will be 1 if in the middle
319 // and 2 if on the right;
320 const bool on_left = ( box.max[dim] < split );
321 const bool on_right = ( box.min[dim] > split );
322 const bool in_middle = !on_left && !on_right;
323 // set the corresponding bits in the bit vector
324 // looks like: [x_1 = 00 | x_2 = 00 | .. | z_1 = 00 | z_2 = 00]
325 // two bits, left = 00, middle = 01, right = 10
326 const int index = 4 * dim + 2 * iteration;
327 if( on_left )
328 {
329 split_data.sizes[0]++;
330 }
331 else if( in_middle )
332 {
333 split_data.sizes[1]++;
334 bits.set( index, 1 );
335 left_line = std::min( left_line, box.min[dim] );
336 right_line = std::max( right_line, box.max[dim] );
337 }
338 else if( on_right )
339 {
340 bits.set( index + 1, 1 );
341 split_data.sizes[2]++;
342 }
343 }
344 #ifdef ELEMENT_TREE_DEBUG
345 std::size_t _count = std::accumulate( split_data.sizes.begin(), split_data.sizes.end(), 0 );
346 std::size_t total = std::distance( begin, end );
347 if( total != _count )
348 {
349 std::cout << total << "vs. " << _count << std::endl;
350 }
351 std::cout << " left_line: " << left_line;
352 std::cout << " right_line: " << right_line << std::endl;
353 std::cout << "co/mputed partition size: ";
354 print_vector( split_data.sizes );
355 std::cout << "-------------------" << std::endl;
356 #endif
357 }
References dim, left_line, moab::common_tree::print_vector(), right_line, and split.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::determine_split().
|
inlineprivate |
Definition at line 401 of file element_tree.hpp.
402 {
403 typedef typename Iterator::value_type Pair;
404 typedef typename Pair::value_type Map_value_type;
405 typedef typename Map_value_type::second_type::second_type Bitset;
406 typedef typename Map_value_type::second_type::first_type Box;
407 typedef typename std::map< std::size_t, Split_data > Splits;
408 typedef typename Splits::value_type Split;
409 typedef _element_tree::Split_comparator< Split > Comparator;
410 Splits splits;
411 for( std::size_t dir = 0; dir < directions.size(); ++dir )
412 {
413 if( directions.test( dir ) )
414 {
415 Split_data split_data( data.bounding_box, dir );
416 compute_split( begin, end, split_data );
417 splits.insert( std::make_pair( 2 * dir, split_data ) );
418 if( update_split_line( split_data ) )
419 {
420 compute_split( begin, end, split_data, true );
421 splits.insert( std::make_pair( 2 * dir + 1, split_data ) );
422 }
423 }
424 }
425 Split best = *std::min_element( splits.begin(), splits.end(), Comparator() );
426 #ifdef ELEMENT_TREE_DEBUG
427 std::cout << "best: " << Comparator().split_objective( best ) << " ";
428 print_vector( best.second.sizes );
429 #endif
430 const int dir = best.first / 2;
431 const int iter = best.first % 2;
432 double& left_rightline = best.second.left_rightline = best.second.bounding_box.min[dir];
433 double& right_leftline = best.second.right_leftline = best.second.bounding_box.max[dir];
434 Bitset mask( 0 );
435 mask.flip( 4 * dir + 2 * iter ).flip( 4 * dir + 2 * iter + 1 );
436 for( Iterator i = begin; i != end; ++i )
437 {
438 Bitset& bits = ( *i )->second.second;
439 const Box& box = ( *i )->second.first;
440 // replace 12 bits with just two.
441 bits &= mask;
442 bits >>= 4 * dir + 2 * iter;
443 // if box is labeled left/right but properly contained
444 // in the middle, move the element into the middle.
445 // we can shrink the size of left/right
446 switch( bits.to_ulong() )
447 {
448 case 0:
449 if( box.max[dir] > best.second.left_line )
450 {
451 left_rightline = std::max( left_rightline, box.max[dir] );
452 }
453 break;
454 case 2:
455 if( box.min[dir] < best.second.right_line )
456 {
457 right_leftline = std::min( right_leftline, box.max[dir] );
458 }
459 break;
460 }
461 }
462 data = best.second;
463 }
References moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::compute_split(), left_rightline, moab::common_tree::print_vector(), right_leftline, and moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::update_split_line().
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::build_tree().
|
inline |
Definition at line 591 of file element_tree.hpp.
592 {
593 typedef typename Vector::const_iterator Point_iterator;
594 typedef typename Box::Pair Pair;
595 typedef typename Pair::first_type Box_iterator;
596 return _find_point( point, 0, result );
597 }
References moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::_find_point().
|
inlineprivate |
Definition at line 360 of file element_tree.hpp.
361 {
362 const int max = 2 * ( data.sizes[2] > data.sizes[0] );
363 const int min = 2 * ( 1 - ( max == 2 ) );
364 bool one_side_empty = data.sizes[max] == 0 || data.sizes[min] == 0;
365 double balance_ratio = data.sizes[max] - data.sizes[min];
366 // if ( !one_side_empty && balance_ratio < .05*total){ return false; }
367 if( !one_side_empty )
368 {
369 // if we have some imbalance on left/right
370 // try to fix the situation
371 balance_ratio /= data.sizes[max];
372 data.split += ( max - 1 ) * balance_ratio * ( data.split / 2.0 );
373 }
374 else
375 {
376 // if the (left) side is empty move the split line just past the
377 // extent of the (left) line of the middle box.
378 // if middle encompasses everything then wiggle
379 // the split line a bit and hope for the best..
380 const double left_distance = std::abs( data.left_line - data.split );
381 const double right_distance = std::abs( data.right_line - data.split );
382 if( ( data.sizes[0] == 0 ) && ( data.sizes[2] != 0 ) )
383 {
384 data.split += right_distance;
385 }
386 else if( data.sizes[2] == 0 && data.sizes[0] != 0 )
387 {
388 data.split -= left_distance;
389 }
390 else
391 {
392 data.split *= 1.05;
393 }
394 }
395 data.left_line = data.right_line = data.split;
396 data.sizes.assign( data.sizes.size(), 0 );
397 return true;
398 }
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::determine_split().
|
private |
Definition at line 606 of file element_tree.hpp.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Element_tree().
|
private |
Definition at line 607 of file element_tree.hpp.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::_find_point().
|
private |
Definition at line 603 of file element_tree.hpp.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Element_tree().
|
private |
Definition at line 605 of file element_tree.hpp.
|
private |
Definition at line 604 of file element_tree.hpp.
Referenced by moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::_find_point(), moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::build_tree(), and moab::Element_tree< _Entity_handles, _Box, _Moab, _Parametrizer >::Element_tree().