DataTransferKit - Multiphysics Solution Transfer Services  2.0
DTK_NodeToNodeOperator_impl.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 /*
3  Copyright (c) 2012, Stuart R. Slattery
4  All rights reserved.
5 
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are
8  met:
9 
10  *: Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12 
13  *: Redistributions in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in the
15  documentation and/or other materials provided with the distribution.
16 
17  *: Neither the name of the University of Wisconsin - Madison nor the
18  names of its contributors may be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 //---------------------------------------------------------------------------//
39 //---------------------------------------------------------------------------//
40 
41 #ifndef DTK_NODETONODE_IMPL_HPP
42 #define DTK_NODETONODE_IMPL_HPP
43 
44 #include "DTK_BasicEntityPredicates.hpp"
46 #include "DTK_DBC.hpp"
49 #include "DTK_PredicateComposition.hpp"
51 
52 #include <Teuchos_ArrayRCP.hpp>
53 #include <Teuchos_CommHelpers.hpp>
54 #include <Teuchos_ParameterList.hpp>
55 #include <Teuchos_Ptr.hpp>
56 
57 #include <Tpetra_MultiVector.hpp>
58 
59 namespace DataTransferKit
60 {
61 //---------------------------------------------------------------------------//
62 // Constructor.
63 template <int DIM>
65  const Teuchos::RCP<const TpetraMap> &domain_map,
66  const Teuchos::RCP<const TpetraMap> &range_map,
67  const Teuchos::ParameterList &parameters )
68  : Base( domain_map, range_map )
69 { /* ... */
70 }
71 
72 //---------------------------------------------------------------------------//
73 // Setup the map operator.
74 template <int DIM>
76  const Teuchos::RCP<FunctionSpace> &domain_space,
77  const Teuchos::RCP<FunctionSpace> &range_space )
78 {
79  DTK_REQUIRE( Teuchos::nonnull( domain_space ) );
80  DTK_REQUIRE( Teuchos::nonnull( range_space ) );
81 
82  // Extract the Support maps.
83  const Teuchos::RCP<const typename Base::TpetraMap> domain_map =
84  this->getDomainMap();
85  const Teuchos::RCP<const typename Base::TpetraMap> range_map =
86  this->getRangeMap();
87 
88  // Get the parallel communicator.
89  Teuchos::RCP<const Teuchos::Comm<int>> comm = domain_map->getComm();
90 
91  // Determine if we have range and domain data on this process.
92  bool nonnull_domain = Teuchos::nonnull( domain_space->entitySet() );
93  bool nonnull_range = Teuchos::nonnull( range_space->entitySet() );
94 
95  // Extract the source nodes and their ids.
96  Teuchos::ArrayRCP<double> source_centers;
97  Teuchos::ArrayRCP<GO> source_support_ids;
98  getNodeCoordsAndIds( domain_space, source_centers, source_support_ids );
99 
100  // Extract the target nodes and their ids.
101  Teuchos::ArrayRCP<double> target_centers;
102  Teuchos::ArrayRCP<GO> target_support_ids;
103  getNodeCoordsAndIds( range_space, target_centers, target_support_ids );
104 
105  // Gather the source centers that are in the proximity of the target
106  // centers on this proc.
107  Teuchos::Array<double> dist_sources;
108  CenterDistributor<DIM> distributor(
109  comm, source_centers(), target_centers(), 1.0e-3, dist_sources );
110 
111  // Gather the global ids of the source centers that are within the proximity
112  // of
113  // the target centers on this proc.
114  Teuchos::Array<GO> dist_source_support_ids( distributor.getNumImports() );
115  Teuchos::ArrayView<const GO> source_support_ids_view = source_support_ids();
116  distributor.distribute( source_support_ids_view,
117  dist_source_support_ids() );
118 
119  // Build the source/target pairings by finding the nearest neighbor - this
120  // should be the exact same node.
121  SplineInterpolationPairing<DIM> pairings( dist_sources, target_centers(),
122  true, 1, 0.0 );
123 
124  // Build the coupling matrix.
125  d_coupling_matrix =
126  Teuchos::rcp( new Tpetra::CrsMatrix<Scalar, LO, GO>( range_map, 1 ) );
127  Teuchos::Array<GO> indices( 1 );
128  Teuchos::Array<double> values( 1, 1.0 );
129  int nn = 0;
130  int local_num_tgt = target_support_ids.size();
131  for ( int i = 0; i < local_num_tgt; ++i )
132  {
133  // If there is no support for this target center then do not build a
134  // local basis.
135  if ( 0 < pairings.childCenterIds( i ).size() )
136  {
137  // If we have a neighbor then there should be only 1.
138  DTK_CHECK( 1 == pairings.childCenterIds( i ).size() );
139 
140  // Check that our neighbor node has the same coordinates.
141  DTK_CHECK(
143  dist_sources( DIM * pairings.childCenterIds( i )[0], DIM )
144  .getRawPtr(),
145  target_centers( DIM * i, DIM ).getRawPtr() ) ) < 1.0e-14 );
146 
147  // Get the id of the domain node
148  indices[0] =
149  dist_source_support_ids[pairings.childCenterIds( i )[0]];
150 
151  // Populate the coupling matrix row.
152  d_coupling_matrix->insertGlobalValues( target_support_ids[i],
153  indices(), values() );
154  }
155  }
156  d_coupling_matrix->fillComplete( domain_map, range_map );
157  DTK_ENSURE( d_coupling_matrix->isFillComplete() );
158 }
159 
160 //---------------------------------------------------------------------------//
161 // Apply the operator.
162 template <int DIM>
163 void NodeToNodeOperator<DIM>::applyImpl( const TpetraMultiVector &X,
164  TpetraMultiVector &Y,
165  Teuchos::ETransp mode, double alpha,
166  double beta ) const
167 {
168  d_coupling_matrix->apply( X, Y, mode, alpha, beta );
169 }
170 
171 //---------------------------------------------------------------------------//
172 // Transpose apply option.
173 template <int DIM>
175 {
176  return true;
177 }
178 
179 //---------------------------------------------------------------------------//
180 // Extract node coordinates and ids from an iterator.
181 template <int DIM>
183  const Teuchos::RCP<FunctionSpace> &space,
184  Teuchos::ArrayRCP<double> &centers,
185  Teuchos::ArrayRCP<GO> &support_ids ) const
186 {
187  // Get an iterator over the local nodes.
188  EntityIterator iterator;
189  if ( Teuchos::nonnull( space->entitySet() ) )
190  {
191  LocalEntityPredicate local_predicate(
192  space->entitySet()->communicator()->getRank() );
193  PredicateFunction predicate = PredicateComposition::And(
194  space->selectFunction(), local_predicate.getFunction() );
195  iterator = space->entitySet()->entityIterator( 0, predicate );
196  }
197 
198  // Extract the coordinates and support ids of the nodes.
199  int local_num_node = iterator.size();
200  centers = Teuchos::ArrayRCP<double>( DIM * local_num_node );
201  support_ids = Teuchos::ArrayRCP<GO>( local_num_node );
202  Teuchos::Array<SupportId> node_supports;
203  EntityIterator begin = iterator.begin();
204  EntityIterator end = iterator.end();
205  int entity_counter = 0;
206  for ( EntityIterator entity = begin; entity != end;
207  ++entity, ++entity_counter )
208  {
209  space->shapeFunction()->entitySupportIds( *entity, node_supports );
210  DTK_CHECK( 1 == node_supports.size() );
211  support_ids[entity_counter] = node_supports[0];
212  space->localMap()->centroid( *entity,
213  centers( DIM * entity_counter, DIM ) );
214  }
215 }
216 
217 //---------------------------------------------------------------------------//
218 
219 } // end namespace DataTransferKit
220 
221 //---------------------------------------------------------------------------//
222 
223 #endif // end DTK_NODETONODE_IMPL_HPP
224 
225 //---------------------------------------------------------------------------//
226 // end DTK_NodeToNodeOperator_impl.hpp
227 //---------------------------------------------------------------------------//
Local source/parent center pairings.
NodeToNodeOperator(const Teuchos::RCP< const TpetraMap > &domain_map, const Teuchos::RCP< const TpetraMap > &range_map, const Teuchos::ParameterList &parameters)
Constructor.
Entity iterator interface.
Parallel node-to-node transfer.
Assertions and Design-by-Contract for error handling.
std::function< bool(Entity)> PredicateFunction
Predicate function typedef.
Definition: DTK_Types.hpp:64
Teuchos::ArrayView< const unsigned > childCenterIds(const unsigned parent_id) const
Given a parent center local id get the ids of the child centers within the given radius.
Global center distributor.
Euclidean distance function.
void distribute(const Teuchos::ArrayView< const T > &source_decomp_data, const Teuchos::ArrayView< T > &target_decomp_data) const
Given a set of scalar values at the given source centers in the source decomposition, distribute them to the target decomposition.
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.
DTK_BasicEntitySet.cpp.
Parallel moving least square interpolator MapOperator implementation.