/*! * \brief Constructor. */ CoarseLocalSearch::CoarseLocalSearch( const EntityIterator& entity_iterator, const Teuchos::RCP<EntityLocalMap>& local_map, const Teuchos::ParameterList& parameters ) { // Setup the centroid array. These will be interleaved. int space_dim = 0; int num_entity = entity_iterator.size(); if ( num_entity > 0 ) { space_dim = entity_iterator.begin()->physicalDimension(); } d_entity_centroids.resize( space_dim * num_entity ); // Add the centroids. EntityIterator entity_it; EntityIterator begin_it = entity_iterator.begin(); EntityIterator end_it = entity_iterator.end(); int entity_local_id = 0; for ( entity_it = begin_it; entity_it != end_it; ++entity_it ) { local_map->centroid( *entity_it, d_entity_centroids(space_dim*entity_local_id,space_dim) ); d_entity_map.emplace( entity_local_id, *entity_it ); ++entity_local_id; } // Build a static search tree. int leaf_size = 20; if ( parameters.isParameter("Coarse Local Search Leaf Size") ) { leaf_size = parameters.get<int>("Coarse Local Search Leaf Size"); } leaf_size = std::min( leaf_size, num_entity ); d_tree = SearchTreeFactory::createStaticTree( space_dim, d_entity_centroids(), leaf_size ); DTK_ENSURE( Teuchos::nonnull(d_tree) ); }
//---------------------------------------------------------------------------// // Assemble the local bounding box around an iterator. void CoarseGlobalSearch::assembleBoundingBox( const EntityIterator& entity_iterator, Teuchos::Tuple<double,6>& bounding_box ) const { double max = std::numeric_limits<double>::max(); bounding_box = Teuchos::tuple( max, max, max, -max, -max, -max ); Teuchos::Tuple<double,6> entity_bounds; EntityIterator entity_begin = entity_iterator.begin(); EntityIterator entity_end = entity_iterator.end(); EntityIterator entity_it; for ( entity_it = entity_begin; entity_it != entity_end; ++entity_it ) { entity_it->boundingBox( entity_bounds ); for ( int n = 0; n < 3; ++n ) { bounding_box[n] = std::min( bounding_box[n], entity_bounds[n] ); bounding_box[n+3] = std::max( bounding_box[n+3], entity_bounds[n+3] ); } } }
//---------------------------------------------------------------------------// // Redistribute a set of range entity centroid coordinates with their owner // ranks to the owning domain process. void CoarseGlobalSearch::search( const EntityIterator& range_iterator, const Teuchos::RCP<EntityLocalMap>& range_local_map, const Teuchos::ParameterList& parameters, Teuchos::Array<EntityId>& range_entity_ids, Teuchos::Array<int>& range_owner_ranks, Teuchos::Array<double>& range_centroids ) const { // Assemble the local range bounding box. Teuchos::Tuple<double,6> range_box; assembleBoundingBox( range_iterator, range_box ); // Find the domain boxes it intersects with. Teuchos::Array<int> neighbor_ranks; Teuchos::Array<Teuchos::Tuple<double,6> > neighbor_boxes; int num_domains = d_domain_boxes.size(); for ( int n = 0; n < num_domains; ++n ) { if ( boxesIntersect(range_box,d_domain_boxes[n],d_inclusion_tol) ) { neighbor_ranks.push_back(n); neighbor_boxes.push_back( d_domain_boxes[n] ); } } // For each local range entity, find the neighbors we should send it to. int num_neighbors = neighbor_boxes.size(); EntityIterator range_begin = range_iterator.begin(); EntityIterator range_end = range_iterator.end(); EntityIterator range_it; Teuchos::Array<EntityId> send_ids; Teuchos::Array<int> send_ranks; Teuchos::Array<double> send_centroids; Teuchos::Array<double> centroid(d_space_dim); bool found_entity = false; for ( range_it = range_begin; range_it != range_end; ++range_it ) { // Get the centroid. range_local_map->centroid( *range_it, centroid() ); // Check the neighbors. found_entity = false; for ( int n = 0; n < num_neighbors; ++n ) { // If the centroid is in the box, add it to the send list. if ( pointInBox(centroid(),neighbor_boxes[n],d_inclusion_tol) ) { found_entity = true; send_ids.push_back( range_it->id() ); send_ranks.push_back( neighbor_ranks[n] ); for ( int d = 0; d < d_space_dim; ++d ) { send_centroids.push_back( centroid[d] ); } } } // If we are tracking missed range entities, add the entity to the // list. if ( d_track_missed_range_entities && !found_entity ) { d_missed_range_entity_ids.push_back( range_it->id() ); } } int num_send = send_ranks.size(); Teuchos::Array<int> range_ranks( num_send, d_comm->getRank() ); // Create a distributor. Tpetra::Distributor distributor(d_comm); int num_range_import = distributor.createFromSends( send_ranks() ); // Redistribute the range entity ids. Teuchos::ArrayView<const EntityId> send_ids_view = send_ids(); range_entity_ids.resize( num_range_import ); distributor.doPostsAndWaits( send_ids_view, 1, range_entity_ids() ); // Redistribute the range entity owner ranks. Teuchos::ArrayView<const int> range_ranks_view = range_ranks(); range_owner_ranks.resize( num_range_import ); distributor.doPostsAndWaits( range_ranks_view, 1, range_owner_ranks() ); // Redistribute the range entity centroids. range_centroids.resize( d_space_dim*num_range_import ); Teuchos::ArrayView<const double> send_centroids_view = send_centroids(); distributor.doPostsAndWaits( send_centroids_view, d_space_dim, range_centroids() ); }