void MovingLeastSquareReconstructionOperator<Scalar,Basis,DIM>::setup( const Teuchos::RCP<const typename Base::TpetraMap>& domain_map, const Teuchos::RCP<FunctionSpace>& domain_space, const Teuchos::RCP<const typename Base::TpetraMap>& range_map, const Teuchos::RCP<FunctionSpace>& range_space, const Teuchos::RCP<Teuchos::ParameterList>& parameters ) { DTK_REQUIRE( Teuchos::nonnull(domain_map) ); DTK_REQUIRE( Teuchos::nonnull(domain_space) ); DTK_REQUIRE( Teuchos::nonnull(range_map) ); DTK_REQUIRE( Teuchos::nonnull(range_space) ); DTK_REQUIRE( Teuchos::nonnull(parameters) ); // 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() ); // Make sure we are applying the map to nodes. DTK_REQUIRE( domain_space->entitySelector()->entityType() == ENTITY_TYPE_NODE ); DTK_REQUIRE( range_space->entitySelector()->entityType() == ENTITY_TYPE_NODE ); // Extract the DOF maps. this->b_domain_map = domain_map; this->b_range_map = range_map; // Extract the source centers and their ids. EntityIterator domain_iterator; if ( nonnull_domain ) { domain_iterator = domain_space->entitySet()->entityIterator( domain_space->entitySelector()->entityType(), domain_space->entitySelector()->selectFunction() ); } int local_num_src = domain_iterator.size(); Teuchos::ArrayRCP<double> source_centers( DIM*local_num_src); Teuchos::ArrayRCP<GO> source_gids( local_num_src ); 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 ) { source_gids[entity_counter] = domain_entity->id(); 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 ) { range_iterator = range_space->entitySet()->entityIterator( range_space->entitySelector()->entityType(), range_space->entitySelector()->selectFunction() ); } int local_num_tgt = range_iterator.size(); Teuchos::ArrayRCP<double> target_centers( DIM*local_num_tgt ); Teuchos::ArrayRCP<GO> target_gids( local_num_tgt ); 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 ) { target_gids[entity_counter] = range_entity->id(); 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 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 radius of // the target centers on this proc. Teuchos::Array<GO> dist_source_gids( distributor.getNumImports() ); Teuchos::ArrayView<const GO> source_gids_view = source_gids(); distributor.distribute( source_gids_view, dist_source_gids() ); // Build the source/target pairings. SplineInterpolationPairing<DIM> pairings( dist_sources, target_centers(), d_radius ); // Build the interpolation matrix. Teuchos::ArrayRCP<std::size_t> children_per_parent = pairings.childrenPerParent(); std::size_t max_entries_per_row = *std::max_element( children_per_parent.begin(), children_per_parent.end() ); Teuchos::RCP<Tpetra::CrsMatrix<Scalar,int,GO> > H = Teuchos::rcp( new Tpetra::CrsMatrix<Scalar,int,GO>( this->b_range_map, max_entries_per_row) ); Teuchos::ArrayView<const Scalar> target_view; Teuchos::Array<GO> indices( max_entries_per_row ); Teuchos::ArrayView<const Scalar> 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_gids[ pair_gids[j] ]; } H->insertGlobalValues( target_gids[i], indices(0,nn), values ); } } H->fillComplete( this->b_domain_map, this->b_range_map ); DTK_ENSURE( H->isFillComplete() ); // Wrap the interpolation matrix in a Thyra wrapper. Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyra_range_vector_space = Thyra::createVectorSpace<Scalar>( H->getRangeMap() ); Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar> > thyra_domain_vector_space = Thyra::createVectorSpace<Scalar>( H->getDomainMap() ); Teuchos::RCP<Thyra::TpetraLinearOp<Scalar,LO,GO> > thyra_H = Teuchos::rcp( new Thyra::TpetraLinearOp<Scalar,LO,GO>() ); thyra_H->initialize( thyra_range_vector_space, thyra_domain_vector_space, H ); // Set the coupling matrix with the base class. this->b_coupling_matrix = thyra_H; DTK_ENSURE( Teuchos::nonnull(this->b_coupling_matrix) ); }
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() ); }