示例#1
0
//---------------------------------------------------------------------------//
// Test that we can remember a value and check it with DBC.
TEUCHOS_UNIT_TEST( DataTransferKitException, remember_test )
{
    DTK_REMEMBER( int test_value_1 = 0 );
    DTK_REMEMBER( int test_value_2 = 1 );
 
    try 
    {
	DTK_CHECK( test_value_1 );
    }
    catch( const DataTransferKit::DataTransferKitException& assertion )
    {
#if HAVE_DTK_DBC
	TEST_ASSERT( 1 );
#else
	TEST_ASSERT( 0 );
#endif
    }
    catch( ... )
    {
#if HAVE_DTK_DBC
	TEST_ASSERT( 0 );
#endif
    }

    try 
    {
	DTK_CHECK( test_value_2 );
	TEST_ASSERT( 1 );
    }
    catch( ... )
    {
	TEST_ASSERT( 0 );
    }
}
Teuchos::Array<double> CloudDomain<2>::center() const
{
    DTK_CHECK( d_bounds[0] <= d_bounds[1] );
    DTK_CHECK( d_bounds[2] <= d_bounds[3] );

    Teuchos::Array<double> center( 2 );
    center[0] = (d_bounds[1]+d_bounds[0]) / 2.0;
    center[1] = (d_bounds[3]+d_bounds[2]) / 2.0;
    return center;
}
bool CloudDomain<2>::pointInDomain( 
    const Teuchos::ArrayView<const double>& coords ) const
{
    DTK_REQUIRE( coords.size() == 2 );
    DTK_CHECK( d_bounds[0] <= d_bounds[1] );
    DTK_CHECK( d_bounds[2] <= d_bounds[3] );

    return ( coords[0] >= d_bounds[0] && coords[0] <= d_bounds[1] &&
	     coords[1] >= d_bounds[2] && coords[1] <= d_bounds[3] )
	? true : false;
}
//---------------------------------------------------------------------------//
// Create the function space.
void STKMeshManager::createFunctionSpace( 
    const BasisType basis_type,
    const PredicateFunction& select_function )
{
    Teuchos::RCP<EntitySet> entity_set = 
	Teuchos::rcp( new STKMeshEntitySet(d_bulk_data) );
    
    Teuchos::RCP<EntityLocalMap> local_map =
	Teuchos::rcp( new STKMeshEntityLocalMap(d_bulk_data) );

    Teuchos::RCP<EntityShapeFunction> shape_function;
    switch( basis_type )
    {
	case BASIS_TYPE_GRADIENT:
	    shape_function = 
		Teuchos::rcp( new STKMeshNodalShapeFunction(d_bulk_data) );
	    break;

	default:
	    bool bad_basis_type = true;
	    DTK_INSIST( !bad_basis_type );
	    break;
    }
    DTK_CHECK( Teuchos::nonnull(shape_function) );

    Teuchos::RCP<EntityIntegrationRule> integration_rule =
	Teuchos::rcp( new STKMeshEntityIntegrationRule(d_bulk_data) );

    d_function_space = Teuchos::rcp( 
	new FunctionSpace(entity_set,local_map,shape_function,
			  integration_rule,select_function) );

    DTK_ENSURE( Teuchos::nonnull(d_function_space) );
}
/*!
 * \brief Find the set of entities a point neighbors.
 */
void CoarseLocalSearch::search( const Teuchos::ArrayView<const double>& point,
				const Teuchos::ParameterList& parameters,
				Teuchos::Array<Entity>& neighbors ) const
{
    // Find the leaf of nearest neighbors.
    int num_neighbors = 100;
    if ( parameters.isParameter("Coarse Local Search kNN") )
    {
	num_neighbors = parameters.get<int>("Coarse Local Search kNN");
    }
    num_neighbors = 
	std::min( num_neighbors, Teuchos::as<int>(d_entity_map.size()) );
    Teuchos::Array<unsigned> local_neighbors = 
	d_tree->nnSearch( point, num_neighbors );

    // Extract the neighbors.
    neighbors.resize( local_neighbors.size() );
    Teuchos::Array<unsigned>::const_iterator local_it;
    Teuchos::Array<Entity>::iterator entity_it;
    for ( local_it = local_neighbors.begin(),
	 entity_it = neighbors.begin();
	  local_it != local_neighbors.end();
	  ++local_it, ++entity_it )
    {
	DTK_CHECK( d_entity_map.count(*local_it) );
	*entity_it = d_entity_map.find(*local_it)->second;
    }
}
示例#6
0
//---------------------------------------------------------------------------//
// Test the invariant check for DBC.
TEUCHOS_UNIT_TEST( DataTransferKitException, invariant_test )
{
    try 
    {
	DTK_CHECK( 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
    }
}
void CloudDomain<2>::expand( const double radius )
{
    DTK_CHECK( radius >= 0.0 );
    d_bounds[0] -= radius;
    d_bounds[1] += radius;    
    d_bounds[2] -= radius;
    d_bounds[3] += radius;    
}
//---------------------------------------------------------------------------//
// 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 );
}
//---------------------------------------------------------------------------//
// 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) );
	}
    }
}
BoundingBox GeometryManager<Geometry,GlobalOrdinal>::localBoundingBox() const
{
    double global_x_min = Teuchos::ScalarTraits<double>::rmax();
    double global_y_min = Teuchos::ScalarTraits<double>::rmax();
    double global_z_min = Teuchos::ScalarTraits<double>::rmax();
    double global_x_max = -Teuchos::ScalarTraits<double>::rmax();
    double global_y_max = -Teuchos::ScalarTraits<double>::rmax();
    double global_z_max = -Teuchos::ScalarTraits<double>::rmax();

    // Get the local bounding boxes compute the local bounding box.
    BoundingBox local_box;
    Teuchos::Tuple<double,6> box_bounds;
    Teuchos::Array<BoundingBox> boxes = boundingBoxes();
    Teuchos::Array<BoundingBox>::const_iterator box_iterator;
    DTK_CHECK( !boxes.empty() );
    for ( box_iterator = boxes.begin();
	  box_iterator != boxes.end();
	  ++box_iterator )
    {
	box_bounds = box_iterator->getBounds();

	if ( box_bounds[0] < global_x_min )
	{
	    global_x_min = box_bounds[0];
	}
	if ( box_bounds[1] < global_y_min )
	{
	    global_y_min = box_bounds[1];
	}
	if ( box_bounds[2] < global_z_min )
	{
	    global_z_min = box_bounds[2];
	}
	if ( box_bounds[3] > global_x_max )
	{
	    global_x_max = box_bounds[3];
	}
	if ( box_bounds[4] > global_y_max )
	{
	    global_y_max = box_bounds[4];
	}
	if ( box_bounds[5] > global_z_max )
	{
	    global_z_max = box_bounds[5];
	}
    }

    return BoundingBox( global_x_min, global_y_min, global_z_min,
			global_x_max, global_y_max, global_z_max );
}
//---------------------------------------------------------------------------//
// Given an entity, get the ids of its support locations
void LibmeshNodalShapeFunction::entitySupportIds( 
    const DataTransferKit::Entity& entity,
    Teuchos::Array<DataTransferKit::SupportId>& support_ids ) const
{
    // Node case.
    if ( 0 == entity.topologicalDimension() )
    {
	DTK_CHECK( extractGeom<libMesh::Node>(entity)->valid_id() );
	support_ids.assign( 1, extractGeom<libMesh::Node>(entity)->id() );
    }

    // Element case.
    else
    {
	Teuchos::Ptr<libMesh::Elem> elem = extractGeom<libMesh::Elem>(entity);
	int num_nodes = elem->n_nodes();
	support_ids.resize( num_nodes );
	for ( int n = 0; n < num_nodes; ++n )
	{
	    DTK_CHECK( elem->get_node(n)->valid_id() );
	    support_ids[n] = elem->get_node(n)->id();
	}
    }
}
//---------------------------------------------------------------------------//
// 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 );
    }
}
NearestNeighborOperator<DeviceType>::NearestNeighborOperator(
    MPI_Comm comm, Kokkos::View<Coordinate const **, DeviceType> source_points,
    Kokkos::View<Coordinate const **, DeviceType> target_points )
    : _comm( comm )
    , _indices( "indices" )
    , _ranks( "ranks" )
    , _size( source_points.extent_int( 0 ) )
{
    // NOTE: instead of checking the pre-condition that there is at least one
    // source point passed to one of the rank, we let the tree handle the
    // communication and just check that the tree is not empty.

    // Build distributed search tree over the source points.
    DistributedSearchTree<DeviceType> search_tree( _comm, source_points );

    // Tree must have at least one leaf, otherwise it makes little sense to
    // perform the search for nearest neighbors.
    DTK_CHECK( !search_tree.empty() );

    // Query nearest neighbor for all target points.
    auto nearest_queries = Details::NearestNeighborOperatorImpl<
        DeviceType>::makeNearestNeighborQueries( target_points );

    // Perform the actual search.
    Kokkos::View<int *, DeviceType> indices( "indices" );
    Kokkos::View<int *, DeviceType> offset( "offset" );
    Kokkos::View<int *, DeviceType> ranks( "ranks" );
    search_tree.query( nearest_queries, indices, offset, ranks );

    // Check post-condition that we did find a nearest neighbor to all target
    // points.
    DTK_ENSURE( lastElement( offset ) == target_points.extent_int( 0 ) );

    // Save results.
    // NOTE: we don't bother keeping `offset` around since it is just `[0, 1, 2,
    // ..., n_target_poins]`
    _indices = indices;
    _ranks = ranks;
}
//---------------------------------------------------------------------------//
// Constructor.
LibmeshVariableField::LibmeshVariableField(
    const Teuchos::RCP<libMesh::MeshBase>& libmesh_mesh,
    const Teuchos::RCP<libMesh::System>& libmesh_system,
    const std::string& variable_name )
    : d_libmesh_mesh( libmesh_mesh )
    , d_libmesh_system( libmesh_system )
{
    // Get ids.
    d_system_id = d_libmesh_system->number();
    d_variable_id = d_libmesh_system->variable_number( variable_name );

    // Get the local support ids.
    libMesh::MeshBase::const_node_iterator nodes_end =
	d_libmesh_mesh->local_nodes_end();
    for ( libMesh::MeshBase::const_node_iterator node_it =
	      d_libmesh_mesh->local_nodes_begin();
	  node_it != nodes_end;
	  ++node_it )
    {
	DTK_CHECK( (*node_it)->valid_id() );
	d_support_ids.push_back( (*node_it)->id() );
    }
}
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;
	}
    }
}
Teuchos::Array<double> CloudDomain<1>::center() const
{
    DTK_CHECK( d_bounds[0] <= d_bounds[1] );
    return Teuchos::Array<double>( 1, (d_bounds[1]+d_bounds[0]) / 2.0 );
}
void MovingLeastSquareReconstructionOperator<Basis,DIM>::setupImpl(
    const Teuchos::RCP<FunctionSpace>& domain_space,
    const Teuchos::RCP<FunctionSpace>& range_space )
{
    DTK_REQUIRE( Teuchos::nonnull(domain_space) );
    DTK_REQUIRE( Teuchos::nonnull(range_space) );

    // Extract the Support maps.
    const Teuchos::RCP<const typename Base::TpetraMap> domain_map
	= this->getDomainMap();
    const Teuchos::RCP<const typename Base::TpetraMap> range_map
	= this->getRangeMap();

    // Get the parallel communicator.
    Teuchos::RCP<const Teuchos::Comm<int> > comm = domain_map->getComm();

    // Determine if we have range and domain data on this process.
    bool nonnull_domain = Teuchos::nonnull( domain_space->entitySet() );
    bool nonnull_range = Teuchos::nonnull( range_space->entitySet() );

    // We will only operate on entities that are locally-owned.
    LocalEntityPredicate local_predicate( comm->getRank() );

    // Extract the source centers from the nodes and their ids.
    EntityIterator domain_iterator;
    if ( nonnull_domain )
    {
	PredicateFunction domain_predicate =
	    PredicateComposition::And(
		domain_space->selectFunction(),	local_predicate.getFunction() );
	domain_iterator =
	    domain_space->entitySet()->entityIterator( d_domain_entity_dim, domain_predicate );
    }
    int local_num_src = domain_iterator.size();
    Teuchos::ArrayRCP<double> source_centers( DIM*local_num_src);
    Teuchos::ArrayRCP<GO> source_support_ids( local_num_src );
    Teuchos::Array<SupportId> source_node_supports;
    EntityIterator domain_begin = domain_iterator.begin();
    EntityIterator domain_end = domain_iterator.end();
    int entity_counter = 0;
    for ( EntityIterator domain_entity = domain_begin;
	  domain_entity != domain_end;
	  ++domain_entity, ++entity_counter )
    {
	domain_space->shapeFunction()->entitySupportIds(
	    *domain_entity, source_node_supports );
	DTK_CHECK( 1 == source_node_supports.size() );
	source_support_ids[entity_counter] = source_node_supports[0];
	domain_space->localMap()->centroid(
	    *domain_entity, source_centers(DIM*entity_counter,DIM) );
    }

    // Extract the target centers and their ids.
    EntityIterator range_iterator;
    if ( nonnull_range )
    {
	PredicateFunction range_predicate =
	    PredicateComposition::And(
		range_space->selectFunction(), local_predicate.getFunction() );
	range_iterator =
	    range_space->entitySet()->entityIterator( d_range_entity_dim, range_predicate );
    } 
    int local_num_tgt = range_iterator.size();
    Teuchos::ArrayRCP<double> target_centers( DIM*local_num_tgt );
    Teuchos::ArrayRCP<GO> target_support_ids( local_num_tgt );
    Teuchos::Array<SupportId> target_node_supports;
    EntityIterator range_begin = range_iterator.begin();
    EntityIterator range_end = range_iterator.end();
    entity_counter = 0;
    for ( EntityIterator range_entity = range_begin;
	  range_entity != range_end;
	  ++range_entity, ++entity_counter )
    {
	range_space->shapeFunction()->entitySupportIds(
	    *range_entity, target_node_supports );
	DTK_CHECK( 1 == target_node_supports.size() );
	target_support_ids[entity_counter] = target_node_supports[0];
	range_space->localMap()->centroid(
	    *range_entity, target_centers(DIM*entity_counter,DIM) );
    }

    // Build the basis.
    Teuchos::RCP<Basis> basis = BP::create( d_radius );

    // Gather the source centers that are within a d_radius of the target
    // centers on this proc.
    Teuchos::Array<double> dist_sources;
    CenterDistributor<DIM> distributor( 
	comm, source_centers(), target_centers(), d_radius, dist_sources );

    // Gather the global ids of the source centers that are within a d_radius of
    // the target centers on this proc.
    Teuchos::Array<GO> dist_source_support_ids( distributor.getNumImports() );
    Teuchos::ArrayView<const GO> source_support_ids_view = source_support_ids();
    distributor.distribute( source_support_ids_view, dist_source_support_ids() );

    // Build the source/target pairings.
    SplineInterpolationPairing<DIM> pairings( 
	dist_sources, target_centers(), d_radius );

    // Build the interpolation matrix.
    Teuchos::ArrayRCP<SupportId> children_per_parent =
	pairings.childrenPerParent();
    SupportId max_entries_per_row = *std::max_element( 
	children_per_parent.begin(), children_per_parent.end() );
    d_coupling_matrix = Teuchos::rcp( new Tpetra::CrsMatrix<Scalar,LO,GO>( 
					  range_map,
					  max_entries_per_row) );
    Teuchos::ArrayView<const double> target_view;
    Teuchos::Array<GO> indices( max_entries_per_row );
    Teuchos::ArrayView<const double> values;
    Teuchos::ArrayView<const unsigned> pair_gids;
    int nn = 0;
    for ( int i = 0; i < local_num_tgt; ++i )
    {
	// If there is no support for this target center then do not build a
	// local basis.
	if ( 0 < pairings.childCenterIds(i).size() )
	{
	    // Get a view of this target center.
	    target_view = target_centers(i*DIM,DIM);

	    // Build the local interpolation problem. 
	    LocalMLSProblem<Basis,DIM> local_problem(
		target_view, pairings.childCenterIds(i),
		dist_sources, *basis );

	    // Get MLS shape function values for this target point.
	    values = local_problem.shapeFunction();
	    nn = values.size();

	    // Populate the interpolation matrix row.
	    pair_gids = pairings.childCenterIds(i);
	    for ( int j = 0; j < nn; ++j )
	    {
		indices[j] = dist_source_support_ids[ pair_gids[j] ];
	    }
	    d_coupling_matrix->insertGlobalValues( 
		target_support_ids[i], indices(0,nn), values );
	}
    }
    d_coupling_matrix->fillComplete( domain_map, range_map );
    DTK_ENSURE( d_coupling_matrix->isFillComplete() );
}
Intrepid::FieldContainer<double> STKMeshHelpers::extractEntityNodeCoordinates( 
    const Teuchos::Array<stk::mesh::Entity>& stk_entities, 
    const stk::mesh::BulkData& bulk_data,
    const int space_dim )
{
    // Cast the field.
    const stk::mesh::FieldBase* coord_field_base= 
	bulk_data.mesh_meta_data().coordinate_field();
    const stk::mesh::Field<double,FieldType>* coord_field =
	dynamic_cast<const stk::mesh::Field<double,FieldType>* >(
	    coord_field_base);

    // Allocate the coordinate array.
    int num_cells = stk_entities.size();
    int num_nodes = 0;
    stk::mesh::EntityRank stk_rank = stk::topology::INVALID_RANK;
    if ( num_cells > 0 )
    {
	stk_rank = bulk_data.entity_rank(stk_entities[0]);
	if ( stk::topology::NODE_RANK == stk_rank )
	{
	    num_nodes = 1;
	}
	else
	{
	    const stk::mesh::Entity* begin = 
		bulk_data.begin_nodes( stk_entities[0] );
	    const stk::mesh::Entity* end = 
		bulk_data.end_nodes( stk_entities[0] );
	    num_nodes = std::distance( begin, end );
	}
    }
    Intrepid::FieldContainer<double> coords( num_cells, num_nodes, space_dim );

    // Extract the coordinates.
    double* node_coords = 0;
    for ( int c = 0; c < num_cells; ++c )
    {
	if ( stk::topology::NODE_RANK == stk_rank )
	{
	    node_coords = stk::mesh::field_data( *coord_field, stk_entities[c] );
	    for ( int d = 0; d < space_dim; ++d )
	    {
		coords(c,0,d) = node_coords[d];
	    }
	}
	else
	{
	    const stk::mesh::Entity* begin = bulk_data.begin_nodes( stk_entities[c] );
	    DTK_REMEMBER(
		const stk::mesh::Entity* end = bulk_data.end_nodes( stk_entities[c] ) 
		);
	    DTK_CHECK( std::distance(begin,end) == num_nodes );
	    for ( int n = 0; n < num_nodes; ++n )
	    {
		node_coords = stk::mesh::field_data( *coord_field, begin[n] );
		for ( int d = 0; d < space_dim; ++d )
		{
		    coords(c,n,d) = node_coords[d];
		}
	    }
	}
    }

    return coords;
}
SplineCoefficientMatrix<Basis,DIM>::SplineCoefficientMatrix(
    const Teuchos::RCP<const Tpetra::Map<int,std::size_t> >& operator_map,
    const Teuchos::ArrayView<const double>& source_centers,
    const Teuchos::ArrayView<const std::size_t>& source_center_gids,
    const Teuchos::ArrayView<const double>& dist_source_centers,
    const Teuchos::ArrayView<const std::size_t>& dist_source_center_gids,
    const SplineInterpolationPairing<DIM>& source_pairings,
    const Basis& basis )
{
    DTK_CHECK( 0 == source_centers.size() % DIM );
    DTK_CHECK( source_centers.size() / DIM == 
		    source_center_gids.size() );
    DTK_CHECK( 0 == dist_source_centers.size() % DIM );
    DTK_CHECK( dist_source_centers.size() / DIM == 
		    dist_source_center_gids.size() );

    // Get the number of source centers.
    unsigned num_source_centers = source_center_gids.size();

    // Create the P matrix.
    int offset = DIM + 1;
    Teuchos::RCP<Tpetra::MultiVector<double,int,std::size_t> > P_vec = 
	Tpetra::createMultiVector<double,int,std::size_t>( operator_map, offset );
    int di = 0; 
    for ( unsigned i = 0; i < num_source_centers; ++i )
    {
	P_vec->replaceGlobalValue( source_center_gids[i], 0, 1.0 );
	di = DIM*i;
	for ( int d = 0; d < DIM; ++d )
	{
	    P_vec->replaceGlobalValue( 
		source_center_gids[i], d+1, source_centers[di+d] );
	}
    }
    d_P =Teuchos::rcp(
	new PolynomialMatrix<std::size_t>(P_vec,operator_map,operator_map) );

    // Create the M matrix.
    Teuchos::ArrayRCP<std::size_t> children_per_parent =
	source_pairings.childrenPerParent();
    std::size_t max_entries_per_row = *std::max_element( 
	children_per_parent.begin(), children_per_parent.end() );
    d_M = Teuchos::rcp( new Tpetra::CrsMatrix<double,int,std::size_t>(
			    operator_map, max_entries_per_row) );
    Teuchos::Array<std::size_t> M_indices( max_entries_per_row );
    Teuchos::Array<double> values( max_entries_per_row );
    int dj = 0;
    Teuchos::ArrayView<const unsigned> source_neighbors;
    double dist = 0.0;
    int nsn = 0;
    for ( unsigned i = 0; i < num_source_centers; ++i )
    {
	// Get the source points neighboring this source point.
    	di = DIM*i;
	source_neighbors = source_pairings.childCenterIds( i );
	nsn = source_neighbors.size();

	// Add the local basis contributions.
    	for ( int j = 0; j < nsn; ++j )
    	{
	    dj = DIM*source_neighbors[j];
	    M_indices[j] = 
		dist_source_center_gids[ source_neighbors[j] ];

	    dist = EuclideanDistance<DIM>::distance(
		&source_centers[di], &dist_source_centers[dj] );

    	    values[j] = BP::evaluateValue( basis, dist );
    	}
	d_M->insertGlobalValues( 
	    source_center_gids[i], M_indices(0,nsn), values(0,nsn) );
    }
    d_M->fillComplete();

    DTK_ENSURE( d_M->isFillComplete() );
}