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;
}