42 #include <unordered_map> 44 #include "DTK_BasicEntityPredicates.hpp" 45 #include "DTK_ConsistentInterpolationOperator.hpp" 47 #include "DTK_ParallelSearch.hpp" 48 #include "DTK_PredicateComposition.hpp" 50 #include <Teuchos_OrdinalTraits.hpp> 52 #include <Tpetra_Distributor.hpp> 53 #include <Tpetra_Map.hpp> 60 const Teuchos::RCP<const TpetraMap> &domain_map,
61 const Teuchos::RCP<const TpetraMap> &range_map,
62 const Teuchos::ParameterList ¶meters )
63 :
Base( domain_map, range_map )
64 , d_range_entity_dim( 0 )
65 , d_keep_missed_sol( false )
66 , d_missed_range_entity_ids( 0 )
69 Teuchos::ParameterList map_list =
70 parameters.sublist(
"Consistent Interpolation" );
71 if ( map_list.isParameter(
"Range Entity Dimension" ) )
73 d_range_entity_dim = map_list.get<
int>(
"Range Entity Dimension" );
77 d_search_list = parameters.sublist(
"Search" );
81 if ( map_list.isParameter(
"Keep Missed Range Data" ) )
83 d_keep_missed_sol = map_list.get<
bool>(
"Keep Missed Range Data" );
84 if ( d_keep_missed_sol )
86 d_search_list.set(
"Track Missed Range Entities",
true );
93 void ConsistentInterpolationOperator::setupImpl(
94 const Teuchos::RCP<FunctionSpace> &domain_space,
95 const Teuchos::RCP<FunctionSpace> &range_space )
97 DTK_REQUIRE( Teuchos::nonnull( domain_space ) );
98 DTK_REQUIRE( Teuchos::nonnull( range_space ) );
101 const Teuchos::RCP<const typename Base::TpetraMap> domain_map =
102 this->getDomainMap();
103 const Teuchos::RCP<const typename Base::TpetraMap> range_map =
107 Teuchos::RCP<const Teuchos::Comm<int>> comm = domain_map->getComm();
110 bool nonnull_domain = Teuchos::nonnull( domain_space->entitySet() );
111 bool nonnull_range = Teuchos::nonnull( range_space->entitySet() );
114 int physical_dimension = 0;
115 if ( nonnull_domain )
117 physical_dimension = domain_space->entitySet()->physicalDimension();
119 else if ( nonnull_range )
121 physical_dimension = range_space->entitySet()->physicalDimension();
126 if ( nonnull_domain )
128 LocalEntityPredicate local_predicate(
129 domain_space->entitySet()->communicator()->getRank() );
131 domain_space->selectFunction(), local_predicate.getFunction() );
132 domain_iterator = domain_space->entitySet()->entityIterator(
133 domain_space->entitySet()->physicalDimension(), domain_predicate );
137 ParallelSearch psearch( comm, physical_dimension, domain_iterator,
138 domain_space->localMap(), d_search_list );
144 LocalEntityPredicate local_predicate(
145 range_space->entitySet()->communicator()->getRank() );
147 range_space->selectFunction(), local_predicate.getFunction() );
148 range_iterator = range_space->entitySet()->entityIterator(
149 d_range_entity_dim, range_predicate );
153 psearch.search( range_iterator, range_space->localMap(), d_search_list );
157 d_missed_range_entity_ids =
158 Teuchos::Array<EntityId>( psearch.getMissedRangeEntityIds() );
164 std::unordered_map<EntityId, GO> range_support_id_map;
165 Teuchos::RCP<Tpetra::Vector<double, int, SupportId>> scale_vector =
166 Tpetra::createVector<double, int, SupportId>( range_map );
170 Teuchos::Array<int> export_ranks;
171 Teuchos::Array<GO> export_data;
172 Teuchos::Array<EntityId> domain_ids;
173 Teuchos::Array<EntityId>::const_iterator domain_id_it;
174 Teuchos::Array<GO> range_support_ids;
178 for ( range_it = range_begin; range_it != range_end; ++range_it )
181 range_space->shapeFunction()->entitySupportIds( *range_it,
183 DTK_CHECK( 1 == range_support_ids.size() );
186 psearch.getDomainEntitiesFromRange( range_it->
id(), domain_ids );
189 DTK_CHECK( range_map->isNodeGlobalElement( range_support_ids[0] ) );
190 scale_vector->replaceGlobalValue( range_support_ids[0],
191 1.0 / domain_ids.size() );
195 for ( domain_id_it = domain_ids.begin();
196 domain_id_it != domain_ids.end(); ++domain_id_it )
198 export_ranks.push_back(
199 psearch.domainEntityOwnerRank( *domain_id_it ) );
201 export_data.push_back( range_support_ids[0] );
202 export_data.push_back( Teuchos::as<GO>( range_it->
id() ) );
208 Tpetra::Distributor range_to_domain_dist( comm );
209 int num_import = range_to_domain_dist.createFromSends( export_ranks() );
210 Teuchos::Array<GO> import_data( 2 * num_import );
211 Teuchos::ArrayView<const GO> export_data_view = export_data();
212 range_to_domain_dist.doPostsAndWaits( export_data_view, 2,
216 for (
int i = 0; i < num_import; ++i )
218 range_support_id_map.emplace(
219 Teuchos::as<EntityId>( import_data[2 * i + 1] ),
220 import_data[2 * i] );
225 d_coupling_matrix = Tpetra::createCrsMatrix<double, LO, GO>( range_map );
228 Teuchos::Array<EntityId> range_entity_ids;
229 Teuchos::Array<EntityId>::const_iterator range_entity_id_it;
230 Teuchos::ArrayView<const double> range_parametric_coords;
231 Teuchos::Array<double> domain_shape_values;
232 Teuchos::Array<double>::iterator domain_shape_it;
233 Teuchos::Array<GO> domain_support_ids;
237 for ( domain_it = domain_begin; domain_it != domain_end; ++domain_it )
240 domain_space->shapeFunction()->entitySupportIds( *domain_it,
241 domain_support_ids );
244 psearch.getRangeEntitiesFromDomain( domain_it->
id(), range_entity_ids );
247 for ( range_entity_id_it = range_entity_ids.begin();
248 range_entity_id_it != range_entity_ids.end();
249 ++range_entity_id_it )
253 psearch.rangeParametricCoordinatesInDomain(
254 domain_it->
id(), *range_entity_id_it, range_parametric_coords );
257 domain_space->shapeFunction()->evaluateValue(
258 *domain_it, range_parametric_coords, domain_shape_values );
259 DTK_CHECK( domain_shape_values.size() ==
260 domain_support_ids.size() );
265 DTK_CHECK( range_support_id_map.count( *range_entity_id_it ) );
266 d_coupling_matrix->insertGlobalValues(
267 range_support_id_map.find( *range_entity_id_it )->second,
268 domain_support_ids(), domain_shape_values() );
273 d_coupling_matrix->fillComplete( domain_map, range_map );
277 d_coupling_matrix->leftScale( *scale_vector );
281 if ( d_keep_missed_sol )
283 d_keep_range_vec = Tpetra::createVector<double, LO, GO>( range_map );
284 for (
auto &m : d_missed_range_entity_ids )
286 d_keep_range_vec->replaceGlobalValue( m, 1.0 );
294 TpetraMultiVector &Y,
295 Teuchos::ETransp mode,
302 Teuchos::RCP<Tpetra::Vector<Scalar, LO, GO>> work_vec;
303 if ( d_keep_missed_sol )
305 DTK_REQUIRE( 0.0 == beta );
306 DTK_REQUIRE( Teuchos::nonnull( d_keep_range_vec ) );
307 work_vec = Tpetra::createVector<double, LO, GO>( this->getRangeMap() );
308 work_vec->elementWiseMultiply( 1.0, *d_keep_range_vec, Y, 0.0 );
312 d_coupling_matrix->apply( X, Y, mode, alpha, beta );
316 if ( d_keep_missed_sol )
318 Y.update( 1.0, *work_vec, 1.0 );
324 bool ConsistentInterpolationOperator::hasTransposeApplyImpl()
const 333 Teuchos::ArrayView<const EntityId>
336 return d_missed_range_entity_ids();
void applyImpl(const TpetraMultiVector &X, TpetraMultiVector &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, double alpha=Teuchos::ScalarTraits< double >::one(), double beta=Teuchos::ScalarTraits< double >::zero()) const override
Apply the operator.
ConsistentInterpolationOperator(const Teuchos::RCP< const TpetraMap > &domain_map, const Teuchos::RCP< const TpetraMap > &range_map, const Teuchos::ParameterList ¶meters)
Constructor.
Entity iterator interface.
Assertions and Design-by-Contract for error handling.
std::function< bool(Entity)> PredicateFunction
Predicate function typedef.
Teuchos::ArrayView< const EntityId > getMissedRangeEntityIds() const
Return the ids of the range entities that were not mapped during the last setup phase (i...
MapOperator Base
Root class tyepdef.
EntityId id() const
Client interface.