Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_DefaultClusteredSpmdProductVector_def.hpp
1// @HEADER
2// *****************************************************************************
3// Thyra: Interfaces and Support for Abstract Numerical Algorithms
4//
5// Copyright 2004 NTESS and the Thyra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef THYRA_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP
11#define THYRA_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP
12
13#include "Thyra_DefaultClusteredSpmdProductVector_decl.hpp"
14#include "Thyra_DefaultClusteredSpmdProductVectorSpace.hpp"
15#include "Thyra_SpmdVectorBase.hpp"
16#include "RTOp_parallel_helpers.h"
17#include "RTOpPack_SPMD_apply_op.hpp"
18#include "Teuchos_Workspace.hpp"
19#include "Teuchos_dyn_cast.hpp"
20#include "Teuchos_implicit_cast.hpp"
21
22
23namespace Thyra {
24
25
26// Constructors/initializers/accessors
27
28
29template <class Scalar>
34
35
36template <class Scalar>
44
45
46template <class Scalar>
49 ,const Teuchos::RCP<VectorBase<Scalar> > vecs[]
50 )
51{
52 // ToDo: Validate input!
53 productSpace_ = productSpace_in;
54 const int numBlocks = productSpace_->numBlocks();
55 vecs_.resize(numBlocks);
56 if(vecs) {
57 std::copy( vecs, vecs + numBlocks, &vecs_[0] );
58 }
59 else {
60 for( int k = 0; k < numBlocks; ++k )
61 vecs_[k] = createMember(productSpace_->getBlock(k));
62 }
63}
64
65
66template <class Scalar>
70 )
71{
72 const int numBlocks = vecs_.size();
73 if(productSpace_in) *productSpace_in = productSpace_;
74 if(vecs) std::copy( &vecs_[0], &vecs_[0]+numBlocks, vecs );
75 productSpace_ = Teuchos::null;
76 vecs_.resize(0);
77}
78
79
80// Overridden from ProductVectorBase
81
82
83template <class Scalar>
86{
88 TEUCHOS_TEST_FOR_EXCEPT( ! ( 0 <= k && k < implicit_cast<int>(vecs_.size()) ) );
89 return vecs_[k];
90}
91
92
93template <class Scalar>
96{
98 TEUCHOS_TEST_FOR_EXCEPT( ! ( 0 <= k && k < implicit_cast<int>(vecs_.size()) ) );
99 return vecs_[k];
100}
101
102
103// Overridden from ProductVectorBase
104
105
106template <class Scalar>
109{
110 return productSpace_;
111}
112
113
114template <class Scalar>
116{
118 TEUCHOS_TEST_FOR_EXCEPT( ! ( 0 <= k && k < implicit_cast<int>(vecs_.size()) ) );
119 return false;
120}
121
122
123template <class Scalar>
126{
127 return getNonconstVectorBlock(k);
128}
129
130
131template <class Scalar>
134{
135 return getVectorBlock(k);
136}
137
138
139// Overridden from VectorBase
140
141
142template <class Scalar>
145{
146 return productSpace_;
147}
148
149
150// Overridden protected members from VectorBase
151
152
153template <class Scalar>
155 const RTOpPack::RTOpT<Scalar> &op,
156 const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
157 const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
158 const Ptr<RTOpPack::ReductTarget> &reduct_obj,
159 const Ordinal global_offset_in
160 ) const
161{
162
163 const Ordinal first_ele_offset_in = 0;
164 const Ordinal sub_dim_in = -1;
165
166 using Teuchos::null;
167 using Teuchos::ptr_dynamic_cast;
168 using Teuchos::tuple;
169
170 const int num_vecs = vecs.size();
171 const int num_targ_vecs = targ_vecs.size();
172
173 // Validate input
174#ifdef TEUCHOS_DEBUG
176 global_offset_in < 0, std::invalid_argument,
177 "DefaultClusteredSpmdProductVector::applyOp(...): Error, "
178 "global_offset_in = " << global_offset_in << " is not acceptable" );
179 bool test_failed;
180 for (int k = 0; k < num_vecs; ++k) {
181 test_failed = !this->space()->isCompatible(*vecs[k]->space());
184 "DefaultClusteredSpmdProductVector::applyOp(...): Error vecs["<<k<<"]->space() "
185 <<"of type \'"<<typeName(*vecs[k]->space())<<"\' is not compatible with this "
186 <<"\'VectorSpaceBlocked\' vector space!"
187 );
188 }
189 for (int k = 0; k < num_targ_vecs; ++k) {
190 test_failed = !this->space()->isCompatible(*targ_vecs[k]->space());
193 ,"DefaultClusteredSpmdProductVector::applyOp(...): Error targ_vecs["<<k<<"]->space() "
194 <<"of type \'"<<typeName(*vecs[k]->space())<<"\' is not compatible with this "
195 <<"\'VectorSpaceBlocked\' vector space!"
196 );
197 }
198#endif
199
200 //
201 // Cast all of the vector arguments to DefaultClusteredSpmdProductVector and
202 // make sure that they are all compatible!
203 //
205 for ( int k = 0; k < num_vecs; ++k ) {
206#ifdef TEUCHOS_DEBUG
207 TEUCHOS_TEST_FOR_EXCEPT(vecs[k]==null);
208#endif
209 cl_vecs[k] = ptr_dynamic_cast<const DefaultClusteredSpmdProductVector<Scalar> >(vecs[k],true);
210 }
211 Array<Ptr<DefaultClusteredSpmdProductVector<Scalar> > > cl_targ_vecs(num_targ_vecs);
212 for ( int k = 0; k < num_targ_vecs; ++k ) {
213#ifdef TEUCHOS_DEBUG
214 TEUCHOS_TEST_FOR_EXCEPT(targ_vecs[k]==null);
215#endif
216 cl_targ_vecs[k] = ptr_dynamic_cast<DefaultClusteredSpmdProductVector<Scalar> >(targ_vecs[k],true);
217 }
218
219 //
220 // Get the overlap of the element for this cluster that will participate in
221 // the RTOp operation.
222 //
224 intraClusterComm = productSpace_->intraClusterComm(),
225 interClusterComm = productSpace_->interClusterComm();
226 const Ordinal
227 clusterSubDim = productSpace_->clusterSubDim(),
228 clusterOffset = productSpace_->clusterOffset(),
229 globalDim = productSpace_->dim();
230 Ordinal overlap_first_cluster_ele_off = 0;
231 Ordinal overlap_cluster_sub_dim = 0;
232 Ordinal overlap_global_off = 0;
233 if (clusterSubDim) {
234 RTOp_parallel_calc_overlap(
235 globalDim,clusterSubDim,clusterOffset,first_ele_offset_in,sub_dim_in
236 ,global_offset_in
237 ,&overlap_first_cluster_ele_off,&overlap_cluster_sub_dim,&overlap_global_off
238 );
239 }
240
241 //
242 // Perform the RTOp for each set of block vectors just within this cluster
243 // of processes.
244 //
246 if (!is_null(reduct_obj))
247 i_reduct_obj = op.reduct_obj_create();
248 // Note: i_reduct_obj will accumulate the reduction within this cluster of
249 // processes.
250 const int numBlocks = vecs_.size();
251 if (overlap_first_cluster_ele_off >=0) {
252
253 //
254 // There is overlap with at least one element in one block
255 // vector for this cluster
256 //
257 Array<Ptr<const VectorBase<Scalar> > > v_vecs(num_vecs);
258 Array<Ptr<VectorBase<Scalar> > > v_targ_vecs(num_targ_vecs);
259 Ordinal overall_global_offset = overlap_global_off;
260 for( int j = 0; j < numBlocks; ++j ) {
262 &v = *vecs_[j];
264 &v_space = *v.space();
265 // Load up the constutuent block SPMD vectors
266 for( int k = 0; k < num_vecs ; ++k )
267 v_vecs[k] = cl_vecs[k]->vecs_[j].ptr();
268 for( int k = 0; k < num_targ_vecs ; ++k )
269 v_targ_vecs[k] = cl_targ_vecs[k]->vecs_[j].ptr();
271 numBlocks > 1, std::logic_error
272 ,"Error, Have not implemented general support for numBlocks > 1!"
273 ); // ToDo: Fix the below code for numBlocks_ > 1!
274 Ordinal v_global_offset = overall_global_offset;
275 // Apply RTOp on just this cluster
276 Thyra::applyOp<Scalar>(
277 op, v_vecs(), v_targ_vecs(), i_reduct_obj.ptr(),
278 v_global_offset);
279 //
280 overall_global_offset += v_space.dim();
281 }
282
283 }
284
285 //
286 // Perform the global reduction across all of the root processes in each of
287 // the clusters and then move the global reduction out to each of the
288 // processes within the cluster.
289 //
290 if (!is_null(reduct_obj)) {
292 icl_reduct_obj = op.reduct_obj_create();
293 // First, accumulate the global reduction across all of the elements by
294 // just performing the global reduction involving the root processes of
295 // each cluster.
296 if (interClusterComm.get()) {
297 RTOpPack::SPMD_all_reduce(
298 &*interClusterComm,
299 op,
300 1,
301 tuple<const RTOpPack::ReductTarget*>(&*i_reduct_obj).getRawPtr(),
302 tuple<RTOpPack::ReductTarget*>(&*icl_reduct_obj).getRawPtr()
303 );
304 }
305 // Now the root processes in each cluster have the full global reduction
306 // across all elements stored in *icl_reduct_obj and the other processes
307 // in each cluster have empty reductions in *icl_reduct_obj. The last
308 // thing to do is to just perform the reduction within each cluster of
309 // processes and to add into the in/out *reduct_obj.
310 RTOpPack::SPMD_all_reduce(
311 &*intraClusterComm,
312 op,
313 1,
314 tuple<const RTOpPack::ReductTarget*>(&*icl_reduct_obj).getRawPtr(),
315 tuple<RTOpPack::ReductTarget*>(&*reduct_obj).getRawPtr()
316 );
317 // ToDo: Replace the above operation with a reduction across clustere into
318 // reduct_obj in the root processes and then broadcast the result to all
319 // of the slave processes.
320 }
321
322}
323
324
325} // namespace Thyra
326
327
328#endif // THYRA_DEFAULT_CLUSTERED_SPMD_PRODUCT_VECTOR_HPP
Teuchos::RCP< ReductTarget > reduct_obj_create() const
Ptr< T > ptr() const
void applyOpImpl(const RTOpPack::RTOpT< Scalar > &op, const ArrayView< const Ptr< const VectorBase< Scalar > > > &vecs, const ArrayView< const Ptr< VectorBase< Scalar > > > &targ_vecs, const Ptr< RTOpPack::ReductTarget > &reduct_obj, const Ordinal global_offset) const
Teuchos::RCP< const ProductVectorSpaceBase< Scalar > > productSpace() const
void uninitialize(Teuchos::RCP< const DefaultClusteredSpmdProductVectorSpace< Scalar > > *productSpace=NULL, Teuchos::RCP< VectorBase< Scalar > > vecs[]=NULL)
Uninitialize.
Teuchos::RCP< const VectorSpaceBase< Scalar > > space() const
void initialize(const Teuchos::RCP< const DefaultClusteredSpmdProductVectorSpace< Scalar > > &productSpace, const Teuchos::RCP< VectorBase< Scalar > > vecs[])
Initialize.
Teuchos::RCP< MultiVectorBase< Scalar > > getNonconstMultiVectorBlock(const int k)
Teuchos::RCP< const VectorBase< Scalar > > getVectorBlock(const int k) const
Teuchos::RCP< const MultiVectorBase< Scalar > > getMultiVectorBlock(const int k) const
Teuchos::RCP< VectorBase< Scalar > > getNonconstVectorBlock(const int k)
DefaultClusteredSpmdProductVector()
Constructs to uninitialized (see postconditions for uninitialize()).
Thrown if vector spaces are incompatible.
Abstract interface for finite-dimensional dense vectors.
virtual RCP< const VectorSpaceBase< Scalar > > space() const =0
Return a smart pointer to the vector space that this vector belongs to.
Abstract interface for objects that represent a space for vectors.
virtual Ordinal dim() const =0
Return the dimension of the vector space.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
TypeTo implicit_cast(const TypeFrom &t)
T_To & dyn_cast(T_From &from)