void GeometryManager<Geometry,GlobalOrdinal>::validate() { // Dimensions greater than 3 are not valid. DTK_REQUIRE( 0 <= d_dim && d_dim <= 3 ); // Check that all local geometries have the same dimension. typename Teuchos::ArrayRCP<Geometry>::const_iterator geom_iterator; for ( geom_iterator = d_geometry.begin(); geom_iterator != d_geometry.end(); ++geom_iterator ) { DTK_REQUIRE( GT::dim( *geom_iterator ) == d_dim ); } // Check that the geometry dimension is the same on every node. Teuchos::Array<int> local_dims( d_comm->getSize(), 0 ); Teuchos::Array<int> local_dims_copy( d_comm->getSize(), 0 ); local_dims[ d_comm->getRank() ] = d_dim; Teuchos::reduceAll<int,int>( *d_comm, Teuchos::REDUCE_SUM, local_dims.size(), &local_dims[0], &local_dims_copy[0] ); Teuchos::Array<int>::iterator unique_bound; std::sort( local_dims_copy.begin(), local_dims_copy.end() ); unique_bound = std::unique( local_dims_copy.begin(), local_dims_copy.end() ); int unique_dim = std::distance( local_dims_copy.begin(), unique_bound ); DTK_REQUIRE( 1 == unique_dim ); local_dims_copy.clear(); }
//---------------------------------------------------------------------------// // Get the parametric coordinates of the range entities in the domain entities. void ParallelSearch::rangeParametricCoordinatesInDomain( const EntityId domain_id, const EntityId range_id, Teuchos::ArrayView<const double>& parametric_coords ) const { DTK_REQUIRE( !d_empty_domain ); DTK_REQUIRE( d_parametric_coords.count(range_id) ); DTK_REQUIRE( d_parametric_coords.find(range_id)->second.count(domain_id) ); parametric_coords = d_parametric_coords.find(range_id)->second.find(domain_id)->second; }
void NearestNeighborOperator<DeviceType>::apply( Kokkos::View<double const *, DeviceType> source_values, Kokkos::View<double *, DeviceType> target_values ) const { // Precondition: check that the source and target are properly sized DTK_REQUIRE( _indices.extent( 0 ) == target_values.extent( 0 ) ); DTK_REQUIRE( _size == source_values.extent_int( 0 ) ); auto values = Details::NearestNeighborOperatorImpl<DeviceType>::fetch( _comm, _ranks, _indices, source_values ); Kokkos::deep_copy( target_values, values ); }
//---------------------------------------------------------------------------// // Get the entity type. EntityType STKMeshEntityImpl::entityType() const { DTK_REQUIRE( Teuchos::nonnull(d_bulk_data) ); stk::mesh::EntityRank rank = d_bulk_data->entity_rank(d_extra_data->d_stk_entity); return STKMeshHelpers::getTypeFromRank( rank, physicalDimension() ); }
double STKMeshField<Scalar,FieldType>::readFieldData( const SupportId support_id, const int dimension ) const { DTK_REQUIRE( d_id_map.count(support_id) ); int local_id = d_id_map.find( support_id )->second; return stk::mesh::field_data(*d_field,d_field_entities[local_id])[dimension]; }
//---------------------------------------------------------------------------// // Test the precondition check for DBC. TEUCHOS_UNIT_TEST( DataTransferKitException, precondition_test ) { try { DTK_REQUIRE( 0 ); throw std::runtime_error( "this shouldn't be thrown" ); } catch( const DataTransferKit::DataTransferKitException& assertion ) { #if HAVE_DTK_DBC std::string message( assertion.what() ); std::string true_message( "DataTransferKit DataTransferKitException: 0, failed in" ); std::string::size_type idx = message.find( true_message ); if ( idx == std::string::npos ) { TEST_ASSERT( 0 ); } #else TEST_ASSERT( 0 ); #endif } catch( ... ) { #if HAVE_DTK_DBC TEST_ASSERT( 0 ); #endif } }
//---------------------------------------------------------------------------// // Get the field for the given string key. Teuchos::RCP<Field> STKMeshManager::field( const std::string& field_name ) const { DTK_REQUIRE( d_field_indexer.count(field_name) ); int field_id = d_field_indexer.find(field_name)->second; return d_fields[ field_id ]; }
Teuchos::ArrayView<typename SharedDomainMap<Mesh,CoordinateField>::GlobalOrdinal> SharedDomainMap<Mesh,CoordinateField>::getMissedTargetPoints() { DTK_REQUIRE( d_store_missed_points ); return d_missed_points(); }
/*! * \brief Constructor. * * \param x_min Minimum x coordinate value in the box. * * \param y_min Minimum y coordinate value in the box. * * \param z_min Minimum z coordinate value in the box. * * \param x_max Maximum x coordinate value in the box. * * \param y_max Maximum y coordinate value in the box. * * \param z_max Maximum z coordinate value in the box. */ BoxImpl::BoxImpl( const EntityId global_id, const int owner_rank, const int block_id, const double x_min, const double y_min, const double z_min, const double x_max, const double y_max, const double z_max ) : d_global_id( global_id ) , d_owner_rank( owner_rank ) , d_block_id( block_id ) , d_x_min( x_min ) , d_y_min( y_min ) , d_z_min( z_min ) , d_x_max( x_max ) , d_y_max( y_max ) , d_z_max( z_max ) { DTK_REQUIRE( d_x_min <= d_x_max ); DTK_REQUIRE( d_y_min <= d_y_max ); DTK_REQUIRE( d_z_min <= d_z_max ); }
AssignFunctor( const View1 view_1, View2 view_2 ) : _view_1( view_1 ) , _view_2( view_2 ) { static_assert( std::is_same<typename View1::traits::value_type, typename View2::traits::value_type>::value, "View data types must be the same" ); static_assert( std::is_same<typename View1::traits::device_type, typename View2::traits::device_type>::value, "View device types must be the same" ); static_assert( static_cast<unsigned>( View1::Rank ) == 2, "View ranks must be 2" ); static_assert( static_cast<unsigned>( View2::Rank ) == 2, "View ranks must be 2" ); DTK_REQUIRE( view_1.extent( 0 ) == view_2.extent( 0 ) ); DTK_REQUIRE( view_1.extent( 1 ) == view_2.extent( 1 ) ); }
void STKMeshField<Scalar,FieldType>::writeFieldData( const SupportId support_id, const int dimension, const double data ) { DTK_REQUIRE( d_id_map.count(support_id) ); int local_id = d_id_map.find( support_id )->second; stk::mesh::field_data(*d_field,d_field_entities[local_id])[dimension] = data; }
/*! * \brief Tuple constructor. * * \param bounds Tuple containing {x_min, y_min, z_min, x_max, y_max, z_max}. */ BoxImpl::BoxImpl( const EntityId global_id, const int owner_rank, const int block_id, const Teuchos::Tuple<double,6>& bounds ) : d_global_id( global_id ) , d_owner_rank( owner_rank ) , d_block_id( block_id ) , d_x_min( bounds[0] ) , d_y_min( bounds[1] ) , d_z_min( bounds[2] ) , d_x_max( bounds[3] ) , d_y_max( bounds[4] ) , d_z_max( bounds[5] ) { DTK_REQUIRE( d_x_min <= d_x_max ); DTK_REQUIRE( d_y_min <= d_y_max ); DTK_REQUIRE( d_z_min <= d_z_max ); }
bool CloudDomain<1>::pointInDomain( const Teuchos::ArrayView<const double>& coords ) const { DTK_REQUIRE( coords.size() == 1 ); DTK_CHECK( d_bounds[0] <= d_bounds[1] ); return ( coords[0] >= d_bounds[0] && coords[0] <= d_bounds[1] ) ? true : false; }
//---------------------------------------------------------------------------// // Given a local support id and a dimension, read data from the application // field. double LibmeshVariableField::readFieldData( const SupportId support_id, const int dimension ) const { DTK_REQUIRE( 0 == dimension ); const libMesh::Node& node = d_libmesh_mesh->node( support_id ); DTK_CHECK( 1 == node.n_comp(d_system_id,d_variable_id) ); libMesh::dof_id_type dof_id = node.dof_number(d_system_id,d_variable_id,0); return d_libmesh_system->current_local_solution->el( dof_id ); }
void IntrepidSideCell<MDArray>::mapToCellPhysicalFrame( const MDArray& parametric_coords, MDArray& physical_coords ) { DTK_REQUIRE( 2 == parametric_coords.rank() ); DTK_REQUIRE( 3 == physical_coords.rank() ); DTK_REQUIRE( parametric_coords.dimension(1) == Teuchos::as<int>(this->d_topology.getDimension()) ); DTK_REQUIRE( physical_coords.dimension(0) == this->d_cell_node_coords.dimension(0) ); DTK_REQUIRE( physical_coords.dimension(1) == parametric_coords.dimension(0) ); DTK_REQUIRE( physical_coords.dimension(2) == Teuchos::as<int>(d_parent_topology.getDimension()) ); MDArray mapped_coords( parametric_coords.dimension(0), d_parent_topology.getDimension() ); Intrepid::CellTools<Scalar>::mapToReferenceSubcell( mapped_coords, parametric_coords, this->d_topology.getDimension(), d_side_id, d_parent_topology ); Intrepid::CellTools<Scalar>::mapToPhysicalFrame( physical_coords, mapped_coords, this->d_cell_node_coords, d_parent_topology ); }
//---------------------------------------------------------------------------// // Given an EntityId, get the entity. void POD_PointCloudEntitySet::getEntity( const EntityId entity_id, const int topological_dimension, Entity& entity ) const { DTK_REQUIRE( 0 == topological_dimension ); DTK_REQUIRE( 1 == std::count(&d_global_ids[0], &d_global_ids[0] + d_num_points, entity_id) ); int local_id = std::distance( &d_global_ids[0], std::find(&d_global_ids[0], &d_global_ids[0] + d_num_points, entity_id) ); entity = POD_PointCloudEntity( d_cloud_coords, d_num_points, d_space_dim, d_layout, entity_id, local_id, d_comm->getRank() ); }
//---------------------------------------------------------------------------// // Get an iterator over a subset of the entity set that satisfies the given // predicate. EntityIterator POD_PointCloudEntitySet::entityIterator( const int topological_dimension, const PredicateFunction& predicate ) const { DTK_REQUIRE( 0 == topological_dimension ); return POD_PointCloudEntityIterator( d_cloud_coords, d_global_ids, d_num_points, d_space_dim, d_layout, d_comm->getRank(), predicate ); }
//---------------------------------------------------------------------------// // Given a domain entity id, get the ids of the range entities that mapped to it. void ParallelSearch::getRangeEntitiesFromDomain( const EntityId domain_id, Teuchos::Array<EntityId>& range_ids ) const { DTK_REQUIRE( !d_empty_domain ); auto domain_pair = d_domain_to_range_map.equal_range( domain_id ); range_ids.resize( std::distance(domain_pair.first,domain_pair.second) ); auto range_it = range_ids.begin(); for ( auto domain_it = domain_pair.first; domain_it != domain_pair.second; ++domain_it, ++range_it ) { *range_it = domain_it->second; } }
//---------------------------------------------------------------------------// // Given a range entity id, get the ids of the domain entities that it mapped to. void ParallelSearch::getDomainEntitiesFromRange( const EntityId range_id, Teuchos::Array<EntityId>& domain_ids ) const { DTK_REQUIRE( !d_empty_range ); auto range_pair = d_range_to_domain_map.equal_range( range_id ); domain_ids.resize( std::distance(range_pair.first,range_pair.second) ); auto domain_it = domain_ids.begin(); for ( auto range_it = range_pair.first; range_it != range_pair.second; ++range_it, ++domain_it ) { *domain_it = range_it->second; } }
//---------------------------------------------------------------------------// // Given a local support id, dimension, and field value, write data into the // application field. void LibmeshVariableField::writeFieldData( const SupportId support_id, const int dimension, const double data ) { DTK_REQUIRE( 0 == dimension ); const libMesh::Node& node = d_libmesh_mesh->node( support_id ); DTK_CHECK( 1 == node.n_comp(d_system_id,d_variable_id) ); if ( node.processor_id() == d_libmesh_system->processor_id() ) { libMesh::dof_id_type dof_id = node.dof_number(d_system_id,d_variable_id,0); d_libmesh_system->solution->set( dof_id, data ); } }
GeometryManager<Geometry,GlobalOrdinal>::GeometryManager( const Teuchos::ArrayRCP<Geometry>& geometry, const Teuchos::ArrayRCP<GlobalOrdinal>& geom_gids, const RCP_Comm& comm, const int dim ) : d_geometry( geometry ) , d_geom_gids( geom_gids ) , d_comm( comm ) , d_dim( dim ) { DTK_REQUIRE( d_geometry.size() == d_geom_gids.size() ); // If we're checking with Design-by-Contract, validate the geometry to the // domain model. #if HAVE_DTK_DBC validate(); #endif }
//---------------------------------------------------------------------------// // Determine if an entity is in the block with the given id. bool STKMeshEntityImpl::inBlock( const int block_id ) const { DTK_REQUIRE( Teuchos::nonnull(d_bulk_data) ); const stk::mesh::PartVector& all_parts = d_bulk_data->mesh_meta_data().get_parts(); stk::mesh::Bucket& entity_bucket = d_bulk_data->bucket( d_extra_data->d_stk_entity ); for ( auto part_it = all_parts.begin(); part_it != all_parts.end(); ++part_it ) { if ( Teuchos::as<int>((*part_it)->mesh_meta_data_ordinal()) == block_id ) { return entity_bucket.member( **part_it ); } } return false; }
std::tuple<std::vector<std::vector<DataTransferKit::Coordinate>>, std::vector<unsigned int>> readInputFile( std::string const &filename ) { std::ifstream file( filename ); DTK_REQUIRE( file.is_open() ); unsigned int dim = 0; file >> dim; // Read the coordinates of the vertices unsigned int n_vertices = 0; file >> n_vertices; std::vector<std::vector<DataTransferKit::Coordinate>> coordinates_ref( n_vertices, std::vector<DataTransferKit::Coordinate>( dim, 0. ) ); for ( unsigned int i = 0; i < n_vertices; ++i ) for ( unsigned int j = 0; j < dim; ++j ) { file >> coordinates_ref[i][j]; } // Read the vertex IDs associated to each cell. unsigned int n_cells = 0; file >> n_cells; // We do know not the size of cell_ref because different cells can have a // different number of vertices std::vector<unsigned int> cells_ref; for ( unsigned int i = 0; i < n_cells; ++i ) { unsigned int n_vertex_per_cell = 0; file >> n_vertex_per_cell; for ( unsigned int j = 0; j < n_vertex_per_cell; ++j ) { unsigned int val = 0; file >> val; cells_ref.push_back( val ); } } file.close(); return std::make_tuple( coordinates_ref, cells_ref ); }
/*! * \brief Determine if a reference point is in the parameterized space of * an entity. */ bool BoxImpl::checkPointInclusion( const double tolerance, const Teuchos::ArrayView<const double>& reference_point ) const { DTK_REQUIRE( 3 == reference_point.size() ); double x_tol = (d_x_max - d_x_min)*tolerance; double y_tol = (d_y_max - d_y_min)*tolerance; double z_tol = (d_z_max - d_z_min)*tolerance; if ( reference_point[0] >= d_x_min - x_tol && reference_point[1] >= d_y_min - y_tol && reference_point[2] >= d_z_min - z_tol && reference_point[0] <= d_x_max + x_tol && reference_point[1] <= d_y_max + y_tol && reference_point[2] <= d_z_max + z_tol ) { return true; } return false; }
//---------------------------------------------------------------------------// // Return the Cartesian bounding box around an entity. void STKMeshEntityImpl::boundingBox( Teuchos::Tuple<double,6>& bounds ) const { DTK_REQUIRE( Teuchos::nonnull(d_bulk_data) ); Intrepid::FieldContainer<double> node_coords = STKMeshHelpers::getEntityNodeCoordinates( Teuchos::Array<stk::mesh::Entity>(1,d_extra_data->d_stk_entity), *d_bulk_data ); DTK_CHECK( node_coords.rank() == 3 ); DTK_CHECK( node_coords.dimension(0) == 1 ); double max = std::numeric_limits<double>::max(); bounds = Teuchos::tuple( max, max, max, -max, -max, -max ); Teuchos::Array<stk::mesh::Entity>::const_iterator entity_node_it; for ( int n = 0; n < node_coords.dimension(1); ++n ) { for ( int d = 0; d < node_coords.dimension(2); ++d ) { bounds[d] = std::min( bounds[d], node_coords(0,n,d) ); bounds[d+3] = std::max( bounds[d+3], node_coords(0,n,d) ); } } }
//---------------------------------------------------------------------------// // Constructor. POD_PointCloudEntityImpl::POD_PointCloudEntityImpl( const double* cloud_coords, const unsigned num_points, const int space_dim, const DataLayout layout, const EntityId global_id, const int local_id, const int owner_rank ) : d_cloud_coords( cloud_coords ) , d_offsets( space_dim, -1 ) , d_global_id( global_id ) , d_owner_rank( owner_rank ) { DTK_REQUIRE( INTERLEAVED == layout || BLOCKED == layout ); // Calculate the offsets into the coordinates array. for ( int d = 0; d < space_dim; ++d ) { d_offsets[d] = ( INTERLEAVED == layout ) ? space_dim*local_id + d : d*num_points + local_id; } }
MovingLeastSquareReconstructionOperator<Basis,DIM>:: MovingLeastSquareReconstructionOperator( const Teuchos::RCP<const TpetraMap>& domain_map, const Teuchos::RCP<const TpetraMap>& range_map, const Teuchos::ParameterList& parameters ) : Base( domain_map, range_map ) , d_domain_entity_dim( 0 ) , d_range_entity_dim( 0 ) { // Get the basis radius. DTK_REQUIRE( parameters.isParameter("RBF Radius") ); d_radius = parameters.get<double>("RBF Radius"); // Get the topological dimension of the domain and range entities. This // map will use their centroids for the point cloud. if ( parameters.isParameter("Domain Entity Dimension") ) { d_domain_entity_dim = parameters.get<int>("Domain Entity Dimension"); } if ( parameters.isParameter("Range Entity Dimension") ) { d_range_entity_dim = parameters.get<int>("Range Entity Dimension"); } }
void SharedDomainMap<Mesh,CoordinateField>::apply( const Teuchos::RCP< FieldEvaluator<GlobalOrdinal,SourceField> >& source_evaluator, Teuchos::RCP< FieldManager<TargetField> >& target_space_manager ) { typedef FieldTraits<SourceField> SFT; typedef FieldTraits<TargetField> TFT; // Set existence values for the source and target. bool source_exists = true; if ( source_evaluator.is_null() ) source_exists = false; bool target_exists = true; if ( target_space_manager.is_null() ) target_exists = false; // Evaluate the source function at the target points and construct a view // of the function evaluations. int source_dim = 0; Teuchos::ArrayRCP<typename SFT::value_type> source_field_copy(0,0); if ( source_exists ) { SourceField function_evaluations = source_evaluator->evaluate( Teuchos::arcpFromArray( d_source_geometry ), Teuchos::arcpFromArray( d_target_coords ) ); source_dim = SFT::dim( function_evaluations ); source_field_copy = FieldTools<SourceField>::copy( function_evaluations ); } Teuchos::broadcast<int,int>( *d_comm, d_source_indexer.l2g(0), Teuchos::Ptr<int>(&source_dim) ); // Build a multivector for the function evaluations. Tpetra::MultiVector<typename SFT::value_type, int, GlobalOrdinal> source_vector( d_source_map, source_dim ); source_vector.get1dViewNonConst().deepCopy( source_field_copy() ); // Construct a view of the target space. int target_dim = 0; Teuchos::ArrayRCP<typename TFT::value_type> target_field_view(0,0); if ( target_exists ) { target_field_view = FieldTools<TargetField>::nonConstView( *target_space_manager->field() ); target_dim = TFT::dim( *target_space_manager->field() ); } Teuchos::broadcast<int,int>( *d_comm, d_target_indexer.l2g(0), Teuchos::Ptr<int>(&target_dim) ); // Check that the source and target have the same field dimension. DTK_REQUIRE( source_dim == target_dim ); // Verify that the target space has the proper amount of memory allocated. if ( target_exists ) { DTK_REQUIRE( target_field_view.size() == Teuchos::as<GlobalOrdinal>( d_target_map->getNodeNumElements()) * target_dim ); } // Build a multivector for the target space. Tpetra::MultiVector<typename TFT::value_type, int, GlobalOrdinal> target_vector( d_target_map, target_dim ); // Fill the target space with zeros so that points we didn't map get some // data. if ( target_exists ) { FieldTools<TargetField>::putScalar( *target_space_manager->field(), 0.0 ); } // Move the data from the source decomposition to the target // decomposition. target_vector.doImport( source_vector, *d_source_to_target_importer, Tpetra::INSERT ); target_field_view.deepCopy( target_vector.get1dView()() ); }
void SharedDomainMap<Mesh,CoordinateField>::setup( const RCP_MeshManager& source_mesh_manager, const RCP_CoordFieldManager& target_coord_manager, double tolerance ) { // Create existence values for the managers. bool source_exists = true; if ( source_mesh_manager.is_null() ) source_exists = false; bool target_exists = true; if ( target_coord_manager.is_null() ) target_exists = false; // Create local to global process indexers for the managers. RCP_Comm source_comm; if ( source_exists ) { source_comm = source_mesh_manager->comm(); } RCP_Comm target_comm; if ( target_exists ) { target_comm = target_coord_manager->comm(); } d_source_indexer = CommIndexer( d_comm, source_comm ); d_target_indexer = CommIndexer( d_comm, target_comm ); // Check the source and target dimensions for consistency. if ( source_exists ) { DTK_REQUIRE( source_mesh_manager->dim() == d_dimension ); } if ( target_exists ) { DTK_REQUIRE( CFT::dim( *target_coord_manager->field() ) == d_dimension ); } // Build the domain space and map from the source information. // ----------------------------------------------------------- // Create an entity set from the local source mesh. Teuchos::RCP<DataTransferKit::ClassicMesh<Mesh> > classic_mesh = Teuchos::rcp( new DataTransferKit::ClassicMesh<Mesh>(source_mesh_manager) ); ClassicMeshEntitySet<Mesh> source_entity_set( classic_mesh ); // Create a local map. ClassicMeshElementLocalMap<Mesh> source_local_map(classic_mesh); // Build the target space and map from the target information. // ----------------------------------------------------------- // Compute a unique global ordinal for each point in the coordinate field. Teuchos::Array<GlobalOrdinal> target_ordinals; computePointOrdinals( target_coord_manager, target_ordinals ); // Create an entity set from the local target points. BasicEntitySet target_entity_set( d_comm, d_dimension ); if ( target_exists ) { Teuchos::ArrayRCP<const typename CFT::value_type> coords_view = FieldTools<CoordinateField>::view( *target_coord_manager->field() ); Teuchos::Array<double> target_coords( d_dimension ); int local_num_targets = target_ordinals.size(); for ( int i = 0; i < local_num_targets; ++i ) { for ( int d = 0; d < d_dimension; ++d ) { target_coords[d] = coords_view[d*local_num_targets + i]; } target_entity_set.addEntity( DataTransferKit::Point( target_ordinals[i], d_comm->getRank(), target_coords ) ); } } // Create a local map. DataTransferKit::BasicGeometryLocalMap target_local_map; // Find the location of the target points in the source mesh. // -------------------------------------------------------------- // Create parameters for the mapping. Teuchos::ParameterList search_list; search_list.set<bool>("Track Missed Range Entities",d_store_missed_points); search_list.set<double>("Point Inclusion Tolerance", 1.0e-9 ); // Do the parallel search. EntityIterator source_iterator = source_entity_set.entityIterator( d_dimension ); EntityIterator target_iterator = target_entity_set.entityIterator( 0 ); ParallelSearch parallel_search( d_comm, d_dimension, source_iterator, Teuchos::rcpFromRef(source_local_map), search_list ); parallel_search.search( target_iterator, Teuchos::rcpFromRef(target_local_map), search_list ); // Build the mapping. // ----------------------- // Get the source-target parings. EntityIterator source_begin = source_iterator.begin(); EntityIterator source_end = source_iterator.end(); Teuchos::Array<EntityId> found_targets; Teuchos::Array<std::pair<EntityId,EntityId> > src_tgt_pairs; for ( auto src_geom = source_begin; src_geom != source_end; ++src_geom ) { // Get the target points found in this source geometry. parallel_search.getRangeEntitiesFromDomain( src_geom->id(), found_targets ); // If we found any points, add them to the mapping. for ( auto found_tgt : found_targets ) { src_tgt_pairs.push_back( std::make_pair(src_geom->id(),found_tgt) ); } } // Filter the source-target pairings so we only find a target point in one // geometry on this process. This handles the local uniqueness // problem. The tpetra import will handle the global uniqueness problem. auto sort_func = [] (std::pair<EntityId,EntityId> a, std::pair<EntityId,EntityId> b ) { return a.second < b.second; }; std::sort( src_tgt_pairs.begin(), src_tgt_pairs.end(), sort_func ); auto unique_func = [] (std::pair<EntityId,EntityId> a, std::pair<EntityId,EntityId> b ) { return a.second == b.second; }; auto unique_it = std::unique( src_tgt_pairs.begin(), src_tgt_pairs.end(), unique_func ); // Extract the mapping data. int num_tgt = std::distance( src_tgt_pairs.begin(), unique_it ); Teuchos::Array<GlobalOrdinal> source_ordinals( num_tgt ); d_source_geometry.resize( num_tgt ); d_target_coords.resize( num_tgt * d_dimension ); Teuchos::ArrayView<const double> tgt_coords; for ( int i = 0; i < num_tgt; ++i ) { // Get the source geom id. d_source_geometry[i] = src_tgt_pairs[i].first; // Get the target point id. source_ordinals[i] = src_tgt_pairs[i].second; // Get the coordinates of the target point. parallel_search.rangeParametricCoordinatesInDomain( src_tgt_pairs[i].first, src_tgt_pairs[i].second, tgt_coords ); for ( int d = 0; d < d_dimension; ++d ) { d_target_coords[ d*num_tgt + i ] = tgt_coords[d]; } } // Create the data map in the source decomposition. d_source_map = Tpetra::createNonContigMap<int,GlobalOrdinal>( source_ordinals(), d_comm ); // Create the data map in the target decomposition. d_target_map = Tpetra::createNonContigMap<int,GlobalOrdinal>( target_ordinals(), d_comm ); // Build the source-to-target importer. d_source_to_target_importer = Teuchos::rcp( new Tpetra::Import<int,GlobalOrdinal>( d_source_map, d_target_map ) ); // Extract the missed points. if ( d_store_missed_points ) { std::unordered_map<GlobalOrdinal,int> target_g2l; int local_num_targets = target_ordinals.size(); for ( int t = 0; t < local_num_targets; ++t ) { target_g2l.emplace( target_ordinals[t], t ); } Teuchos::ArrayView<const EntityId> missed = parallel_search.getMissedRangeEntityIds(); int num_missed = missed.size(); d_missed_points.resize( num_missed ); for ( int i = 0; i < num_missed; ++i ) { DTK_CHECK( target_g2l.count(missed[i]) ); d_missed_points[i] = target_g2l.find( missed[i] )->second; } } }
//---------------------------------------------------------------------------// // Get the domain map. Teuchos::RCP<const typename MapOperator::TpetraMap> MapOperator::getRangeMap() const { DTK_REQUIRE( Teuchos::nonnull(d_range_map) ); return d_range_map; }