DataTransferKit - Multiphysics Solution Transfer Services  2.0
DTK_CoarseGlobalSearch.cpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 /*
3  Copyright (c) 2012, Stuart R. Slattery
4  All rights reserved.
5 
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are
8  met:
9 
10  *: Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12 
13  *: Redistributions in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in the
15  documentation and/or other materials provided with the distribution.
16 
17  *: Neither the name of the University of Wisconsin - Madison nor the
18  names of its contributors may be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 //---------------------------------------------------------------------------//
39 //---------------------------------------------------------------------------//
40 
41 #include <limits>
42 
44 
45 #include <Teuchos_CommHelpers.hpp>
46 
47 #include <Tpetra_Distributor.hpp>
48 
49 namespace DataTransferKit
50 {
51 //---------------------------------------------------------------------------//
52 // Constructor.
53 CoarseGlobalSearch::CoarseGlobalSearch(
54  const Teuchos::RCP<const Teuchos::Comm<int>> &comm,
55  const int physical_dimension, const EntityIterator &domain_iterator,
56  const Teuchos::ParameterList &parameters )
57  : d_comm( comm )
58  , d_space_dim( physical_dimension )
59  , d_track_missed_range_entities( false )
60  , d_missed_range_entity_ids( 0 )
61  , d_inclusion_tol( 1.0e-6 )
62 {
63  // Determine if we are tracking missed range entities.
64  if ( parameters.isParameter( "Track Missed Range Entities" ) )
65  {
66  d_track_missed_range_entities =
67  parameters.get<bool>( "Track Missed Range Entities" );
68  }
69 
70  // Get the point inclusion tolerance.
71  if ( parameters.isParameter( "Point Inclusion Tolerance" ) )
72  {
73  d_inclusion_tol = parameters.get<double>( "Point Inclusion Tolerance" );
74  }
75 
76  // Assemble the local domain bounding box.
77  Teuchos::Tuple<double, 6> domain_box;
78  assembleBoundingBox( domain_iterator, domain_box );
79 
80  // Gather the bounding boxes from all domains.
81  int comm_size = d_comm->getSize();
82  Teuchos::Array<double> all_bounds( 6 * comm_size );
83  Teuchos::gatherAll<int, double>( *d_comm, 6, domain_box.getRawPtr(),
84  all_bounds.size(),
85  all_bounds.getRawPtr() );
86 
87  // Extract the bounding boxes.
88  d_domain_boxes.resize( comm_size );
89  int id = 0;
90  for ( int n = 0; n < comm_size; ++n )
91  {
92  id = 6 * n;
93  d_domain_boxes[n] = Teuchos::tuple(
94  all_bounds[id], all_bounds[id + 1], all_bounds[id + 2],
95  all_bounds[id + 3], all_bounds[id + 4], all_bounds[id + 5] );
96  }
97 }
98 
99 //---------------------------------------------------------------------------//
100 // Redistribute a set of range entity centroid coordinates with their owner
101 // ranks to the owning domain process.
102 void CoarseGlobalSearch::search(
103  const EntityIterator &range_iterator,
104  const Teuchos::RCP<EntityLocalMap> &range_local_map,
105  const Teuchos::ParameterList &parameters,
106  Teuchos::Array<EntityId> &range_entity_ids,
107  Teuchos::Array<int> &range_owner_ranks,
108  Teuchos::Array<double> &range_centroids ) const
109 {
110  // Assemble the local range bounding box.
111  Teuchos::Tuple<double, 6> range_box;
112  assembleBoundingBox( range_iterator, range_box );
113 
114  // Find the domain boxes it intersects with.
115  Teuchos::Array<int> neighbor_ranks;
116  Teuchos::Array<Teuchos::Tuple<double, 6>> neighbor_boxes;
117  int num_domains = d_domain_boxes.size();
118  for ( int n = 0; n < num_domains; ++n )
119  {
120  if ( boxesIntersect( range_box, d_domain_boxes[n], d_inclusion_tol ) )
121  {
122  neighbor_ranks.push_back( n );
123  neighbor_boxes.push_back( d_domain_boxes[n] );
124  }
125  }
126 
127  // For each local range entity, find the neighbors we should send it to.
128  int num_neighbors = neighbor_boxes.size();
129  EntityIterator range_begin = range_iterator.begin();
130  EntityIterator range_end = range_iterator.end();
131  EntityIterator range_it;
132  Teuchos::Array<EntityId> send_ids;
133  Teuchos::Array<int> send_ranks;
134  Teuchos::Array<double> send_centroids;
135  Teuchos::Array<double> centroid( d_space_dim );
136  bool found_entity = false;
137  for ( range_it = range_begin; range_it != range_end; ++range_it )
138  {
139  // Get the centroid.
140  range_local_map->centroid( *range_it, centroid() );
141 
142  // Check the neighbors.
143  found_entity = false;
144  for ( int n = 0; n < num_neighbors; ++n )
145  {
146  // If the centroid is in the box, add it to the send list.
147  if ( pointInBox( centroid(), neighbor_boxes[n], d_inclusion_tol ) )
148  {
149  found_entity = true;
150  send_ids.push_back( range_it->id() );
151  send_ranks.push_back( neighbor_ranks[n] );
152  for ( int d = 0; d < d_space_dim; ++d )
153  {
154  send_centroids.push_back( centroid[d] );
155  }
156  }
157  }
158 
159  // If we are tracking missed range entities, add the entity to the
160  // list.
161  if ( d_track_missed_range_entities && !found_entity )
162  {
163  d_missed_range_entity_ids.push_back( range_it->id() );
164  }
165  }
166  int num_send = send_ranks.size();
167  Teuchos::Array<int> range_ranks( num_send, d_comm->getRank() );
168 
169  // Create a distributor.
170  Tpetra::Distributor distributor( d_comm );
171  int num_range_import = distributor.createFromSends( send_ranks() );
172 
173  // Redistribute the range entity ids.
174  Teuchos::ArrayView<const EntityId> send_ids_view = send_ids();
175  range_entity_ids.resize( num_range_import );
176  distributor.doPostsAndWaits( send_ids_view, 1, range_entity_ids() );
177 
178  // Redistribute the range entity owner ranks.
179  Teuchos::ArrayView<const int> range_ranks_view = range_ranks();
180  range_owner_ranks.resize( num_range_import );
181  distributor.doPostsAndWaits( range_ranks_view, 1, range_owner_ranks() );
182 
183  // Redistribute the range entity centroids.
184  range_centroids.resize( d_space_dim * num_range_import );
185  Teuchos::ArrayView<const double> send_centroids_view = send_centroids();
186  distributor.doPostsAndWaits( send_centroids_view, d_space_dim,
187  range_centroids() );
188 }
189 
190 //---------------------------------------------------------------------------//
191 // Return the ids of the range entities that were not mapped during the last
192 // setup phase (i.e. those that are guaranteed to not receive data from the
193 // transfer).
194 Teuchos::ArrayView<const EntityId>
196 {
197  return d_missed_range_entity_ids();
198 }
199 
200 //---------------------------------------------------------------------------//
201 // Assemble the local bounding box around an iterator.
202 void CoarseGlobalSearch::assembleBoundingBox(
203  const EntityIterator &entity_iterator,
204  Teuchos::Tuple<double, 6> &bounding_box ) const
205 {
206  if ( entity_iterator.size() > 0 )
207  {
208  double max = std::numeric_limits<double>::max();
209  bounding_box = Teuchos::tuple( max, max, max, -max, -max, -max );
210  Teuchos::Tuple<double, 6> entity_bounds;
211  EntityIterator entity_begin = entity_iterator.begin();
212  EntityIterator entity_end = entity_iterator.end();
213  EntityIterator entity_it;
214  for ( entity_it = entity_begin; entity_it != entity_end; ++entity_it )
215  {
216  entity_it->boundingBox( entity_bounds );
217  for ( int n = 0; n < 3; ++n )
218  {
219  bounding_box[n] = std::min( bounding_box[n], entity_bounds[n] );
220  bounding_box[n + 3] =
221  std::max( bounding_box[n + 3], entity_bounds[n + 3] );
222  }
223  }
224  }
225  else
226  {
227  bounding_box = Teuchos::tuple( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
228  }
229 }
230 
231 //---------------------------------------------------------------------------//
232 
233 } // end namespace DataTransferKit
234 
235 //---------------------------------------------------------------------------//
236 // end CoarseGlobalSearch.cpp
237 //---------------------------------------------------------------------------//
CoarseGlobalSearch declaration.
void boundingBox(Teuchos::Tuple< double, 6 > &bounds) const
Return the Cartesian bounding box around an entity.
Definition: DTK_Entity.cpp:114
Entity iterator interface.
Teuchos::ArrayView< const EntityId > getMissedRangeEntityIds() const
Return the ids of the range entities that were not during the last search (i.e. those that are guaran...
DTK_BasicEntitySet.cpp.