Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_SpmdVectorDefaultBase_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_SPMD_VECTOR_DEFAULT_BASE_DEF_HPP
11 #define THYRA_SPMD_VECTOR_DEFAULT_BASE_DEF_HPP
12 
13 // disable clang warnings
14 #if defined (__clang__) && !defined (__INTEL_COMPILER)
15 #pragma clang system_header
16 #endif
17 
18 #include "Thyra_SpmdVectorDefaultBase_decl.hpp"
19 #include "Thyra_VectorDefaultBase.hpp"
20 #include "Thyra_SpmdVectorSpaceDefaultBase.hpp"
21 #include "Thyra_apply_op_helper.hpp"
22 #include "Thyra_SpmdLocalDataAccess.hpp"
23 #include "RTOpPack_SPMD_apply_op.hpp"
24 #include "Teuchos_Workspace.hpp"
25 #include "Teuchos_Assert.hpp"
26 #include "Teuchos_dyn_cast.hpp"
27 #include "Teuchos_Assert.hpp"
28 #include "Teuchos_Range1D.hpp"
29 
30 namespace Thyra {
31 
32 
33 // Public interface functions
34 
35 
36 template<class Scalar>
38  :globalDim_(0)
39  ,localOffset_(-1)
40  ,localSubDim_(0)
41 {}
42 
43 
44 template<class Scalar>
46  const Ptr<const Teuchos::Comm<Ordinal> > &comm_in,
47  const RTOpPack::RTOpT<Scalar> &op,
48  const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
49  const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
50  const Ptr<RTOpPack::ReductTarget> &reduct_obj,
51  const Ordinal global_offset_in
52  ) const
53 {
54 
55  using Teuchos::null;
56  using Teuchos::dyn_cast;
57  using Teuchos::Workspace;
58  using Teuchos::rcpFromPtr;
59 
60  const int num_vecs = vecs.size();
61  const int num_targ_vecs = targ_vecs.size();
62 
64  const SpmdVectorSpaceBase<Scalar> &spmdSpc = *this->spmdSpace();
65 
66 #ifdef TEUCHOS_DEBUG
68  "SpmdVectorDefaultBase<>::applyOp(...)",*space(),
69  op, vecs, targ_vecs, reduct_obj, global_offset_in);
70 #endif
71 
73  if (nonnull(comm_in))
74  comm = Teuchos::rcpFromPtr(comm_in);
75  else
76  comm = spmdSpc.getComm();
77 
78  // First see if this is a locally replicated vector in which case
79  // we treat this as a local operation only.
80  const bool locallyReplicated = spmdSpc.isLocallyReplicated();
81 
82  const Range1D local_rng(localOffset_, localOffset_+localSubDim_-1);
83 
84  // Create sub-vector views of all of the *participating* local data
85  Workspace<RTOpPack::ConstSubVectorView<Scalar> > sub_vecs(wss.get(), num_vecs);
86  Workspace<RTOpPack::SubVectorView<Scalar> > sub_targ_vecs(wss.get(), num_targ_vecs);
87  for(int k = 0; k < num_vecs; ++k ) {
88  sub_vecs[k] = getLocalSubVectorView<Scalar>(rcpFromPtr(vecs[k]));
89  sub_vecs[k].setGlobalOffset(localOffset_+global_offset_in);
90  }
91  for(int k = 0; k < num_targ_vecs; ++k ) {
92  sub_targ_vecs[k] = getNonconstLocalSubVectorView<Scalar>(rcpFromPtr(targ_vecs[k]));
93  sub_targ_vecs[k].setGlobalOffset(localOffset_+global_offset_in);
94  }
95 
96  // Apply the RTOp operator object (all processors must participate)
97  RTOpPack::SPMD_apply_op(
98  locallyReplicated ? NULL : &*comm, // comm
99  op, // op
100  num_vecs, // num_vecs
101  sub_vecs.getRawPtr(), // sub_vecs
102  num_targ_vecs, // num_targ_vecs
103  sub_targ_vecs.getRawPtr(), // targ_sub_vecs
104  reduct_obj.get() // reduct_obj
105  );
106 
107  // Free and commit the local data
108  for (int k = 0; k < num_vecs; ++k ) {
109  sub_vecs[k] = RTOpPack::ConstSubVectorView<Scalar>();
110  }
111  for (int k = 0; k < num_targ_vecs; ++k ) {
112  sub_targ_vecs[k] = RTOpPack::SubVectorView<Scalar>();
113  }
114 
115 }
116 
117 
118 // Overridden from Teuchos::Describable
119 
120 
121 template<class Scalar>
123 {
124  using Teuchos::RCP; using Teuchos::Comm; using Teuchos::null;
125  using Teuchos::typeName;
126  std::ostringstream ostr;
127  ostr<<typeName(*this)<<"{spmdSpace="<<this->spmdSpace()->description()<<"}";
128  return ostr.str();
129 }
130 
131 
132 // Overridden public functions from VectorBase
133 
134 
135 template<class Scalar>
138 {
139  return this->spmdSpace();
140 }
141 
142 
143 // protected
144 
145 
146 // Overridden protected functions from VectorBase
147 
148 
149 template<class Scalar>
151  const RTOpPack::RTOpT<Scalar> &op,
152  const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
153  const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
154  const Ptr<RTOpPack::ReductTarget> &reduct_obj,
155  const Ordinal global_offset
156  ) const
157 {
158  applyOpImplWithComm( Teuchos::null, op, vecs, targ_vecs, reduct_obj,
159  global_offset);
160 }
161 
162 
163 template<class Scalar>
165  const Range1D& rng_in, RTOpPack::ConstSubVectorView<Scalar>* sub_vec
166  ) const
167 {
168 #ifdef THYRA_DEBUG
169  TEUCHOS_ASSERT(sub_vec);
170 #endif
171  if( rng_in == Range1D::INVALID ) {
172  // Just return an null view
174  return;
175  }
176  const bool isFullRng = rng_in.full_range();
177  const Range1D rng = validateRange(rng_in);
178  const bool isLocallyReplicated = this->spmdSpace()->isLocallyReplicated();
179  if (
180  (
181  rng.lbound() < localOffset_
182  ||
183  localOffset_+localSubDim_-1 < rng.ubound()
184  ||
185  isFullRng
186  )
187  &&
188  !isLocallyReplicated
189  )
190  {
191  // rng consists of off-processor elements so use the default implementation!
193  return;
194  }
195  // rng consists of all local data so get it!
196  ArrayRCP<const Scalar>localValues;
197  this->getLocalData(Teuchos::outArg(localValues));
198  sub_vec->initialize(
199  rng.lbound(), // globalOffset
200  rng.size(), // subDim
201  localValues.persistingView(rng.lbound()-localOffset_, rng.size()),
202  1 // stride
203  );
204 }
205 
206 
207 template<class Scalar>
210  ) const
211 {
212 #ifdef TEUCHOS_DEBUG
214  sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
215  ,std::logic_error
216  ,"SpmdVectorDefaultBase<Scalar>::releaseDetachedVectorViewImpl(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
217  );
218 #endif
219  if(
220  sub_vec->globalOffset() < localOffset_
221  || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
222  )
223  {
224  // Let the default implementation handle it!
226  return;
227  }
228  // Nothing to deallocate!
229  sub_vec->uninitialize();
230 }
231 
232 
233 template<class Scalar>
235  const Range1D& rng_in, RTOpPack::SubVectorView<Scalar>* sub_vec
236  )
237 {
238 #ifdef THYRA_DEBUG
239  TEUCHOS_ASSERT(sub_vec);
240 #endif
241  if( rng_in == Range1D::INVALID ) {
242  // Just return an null view
243  *sub_vec = RTOpPack::SubVectorView<Scalar>();
244  return;
245  }
246  const bool isFullRng = rng_in.full_range();
247  const Range1D rng = validateRange(rng_in);
248  const bool isLocallyReplicated = this->spmdSpace()->isLocallyReplicated();
249  if (
250  (
251  rng.lbound() < localOffset_
252  ||
253  localOffset_+localSubDim_-1 < rng.ubound()
254  ||
255  isFullRng
256  )
257  &&
258  !isLocallyReplicated
259  )
260  {
261  // rng consists of off-processor elements so use the default implementation!
263  return;
264  }
265  // rng consists of all local data so get it!
266  ArrayRCP<Scalar> localValues;
267  this->getNonconstLocalData(Teuchos::outArg(localValues));
268  sub_vec->initialize(
269  rng.lbound(), // globalOffset
270  rng.size(), // subDim
271  localValues.persistingView(rng.lbound()-localOffset_, rng.size()),
272  1 // stride
273  );
274 }
275 
276 
277 template<class Scalar>
280  )
281 {
282 #ifdef TEUCHOS_DEBUG
284  sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
285  ,std::logic_error
286  ,"SpmdVectorDefaultBase<Scalar>::commitDetachedView(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
287  );
288 #endif
289  if(
290  sub_vec->globalOffset() < localOffset_
291  ||
292  localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
293  )
294  {
295  // Let the default implementation handle it!
297  return;
298  }
299  sub_vec->uninitialize(); // Nothing to deallocate!
300 }
301 
302 
303 // Overridden Protected functions from SpmdMultiVectorBase
304 
305 
306 template<class Scalar>
309 {
310  ArrayRCP<Scalar> localValues;
311  this->getNonconstLocalData(Teuchos::outArg(localValues));
313  localOffset_, // globalOffset
314  localSubDim_,
315  0, // colOffset
316  1, // numCols
317  localValues,
318  localSubDim_ // leadingDim
319  );
320 }
321 
322 
323 template<class Scalar>
326 {
327  using Teuchos::outArg;
328  ArrayRCP<const Scalar> localValues;
329  this->getLocalData(outArg(localValues));
331  localOffset_, // globalOffset
332  localSubDim_,
333  0, // colOffset
334  1, // numCols
335  localValues,
336  localSubDim_ // leadingDim
337  );
338 }
339 
340 
341 template<class Scalar>
343  const Ptr<ArrayRCP<Scalar> > &localValues, const Ptr<Ordinal> &leadingDim)
344 {
345  this->getNonconstLocalData(localValues);
346  *leadingDim = localValues->size();
347 }
348 
349 
350 template<class Scalar>
352  const Ptr<ArrayRCP<const Scalar> > &localValues, const Ptr<Ordinal> &leadingDim) const
353 {
354  this->getLocalData(localValues);
355  *leadingDim = localValues->size();
356 }
357 
358 
359 // Overridden Protected functions from SpmdVectorBase
360 
361 
362 template<class Scalar>
365 {
366  ArrayRCP<Scalar> localValues;
367  this->getNonconstLocalData(Teuchos::outArg(localValues));
369  localOffset_,
370  localSubDim_,
371  localValues,
372  1 // stride
373  );
374 }
375 
376 
377 template<class Scalar>
380 {
381  ArrayRCP<const Scalar> localValues;
382  this->getLocalData(Teuchos::outArg(localValues));
384  localOffset_, // globalOffset?
385  localSubDim_,
386  localValues,
387  1 // stride
388  );
389 }
390 
391 
392 // Protected functions to be used by subclasses
393 
394 
395 template<class Scalar>
397 {
398  if(globalDim_ == 0) {
399  const SpmdVectorSpaceBase<Scalar> *l_spmdSpace = this->spmdSpace().get();
400  if(l_spmdSpace) {
401  globalDim_ = l_spmdSpace->dim();
402  localOffset_ = l_spmdSpace->localOffset();
403  localSubDim_ = l_spmdSpace->localSubDim();
404  }
405  else {
406  globalDim_ = 0;
407  localOffset_ = -1;
408  localSubDim_ = 0;
409  }
410  }
411 }
412 
413 
414 // private
415 
416 
417 template<class Scalar>
419 {
420  const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
421 #ifdef TEUCHOS_DEBUG
423  !(0 <= rng.lbound() && rng.ubound() < globalDim_), std::invalid_argument
424  ,"SpmdVectorDefaultBase<Scalar>::validateRange(...): Error, the range ["
425  <<rng.lbound()<<","<<rng.ubound()<<"] is not "
426  "in the range [0,"<<(globalDim_-1)<<"]!"
427  );
428 #endif
429  return rng;
430 }
431 
432 
433 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
434 template<class Scalar>
435 bool SpmdVectorDefaultBase<Scalar>::show_dump = false;
436 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
437 
438 
439 } // end namespace Thyra
440 
441 
442 #endif // THYRA_SPMD_VECTOR_DEFAULT_BASE_DEF_HPP
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
Calls applyOpImplWithComm(null,op,...).
size_t size() const
RTOpPack::SubVectorView< Scalar > getNonconstLocalSubVectorImpl()
Virtual implementation for getNonconstLocalSubVector().
ArrayRCP< T > persistingView(size_type lowerOffset, size_type size) const
void acquireDetachedVectorViewImpl(const Range1D &rng, RTOpPack::ConstSubVectorView< Scalar > *sub_vec) const
Implemented through this-&gt;getLocalData()
void apply_op_validate_input(const std::string &func_name, const VectorSpaceBase< Scalar > &space, 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)
Validate the inputs to VectorBase::applyOp().
virtual void releaseDetachedVectorViewImpl(RTOpPack::ConstSubVectorView< Scalar > *sub_vec) const
virtual void applyOpImplWithComm(const Ptr< const Teuchos::Comm< Ordinal > > &comm, 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
Implementation of applyOpImpl(...) that uses an input Comm.
Base class for SPMD vectors that can provide views of contiguous elements in a process.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
T_To & dyn_cast(T_From &from)
Ordinal ubound() const
bool full_range() const
RTOpPack::SubMultiVectorView< Scalar > getNonconstLocalSubMultiVectorImpl()
virtual void updateSpmdSpace()
Subclasses must call this function whenever the structure of the VectorSpaceBase changes.
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
void initialize(Ordinal globalOffset_in, Ordinal subDim_in, const ArrayRCP< Scalar > &values_in, ptrdiff_t stride_in)
Abstract interface for finite-dimensional dense vectors.
Teuchos::RCP< const VectorSpaceBase< Scalar > > space() const
Returns this-&gt;spmdSpace().
RTOpPack::ConstSubMultiVectorView< Scalar > getLocalSubMultiVectorImpl() const
Ordinal globalOffset() const
void commitNonconstDetachedVectorViewImpl(RTOpPack::SubVectorView< Scalar > *sub_vec)
Implemented through this-&gt;commitLocalData()
Ordinal lbound() const
bool nonnull(const boost::shared_ptr< T > &p)
virtual Teuchos::RCP< const Teuchos::Comm< Ordinal > > getComm() const =0
Returns the SPMD communicator.
virtual Ordinal localOffset() const =0
Returns the offset for the local sub-vector stored on this process.
RTOpPack::ConstSubVectorView< Scalar > getLocalSubVectorImpl() const
Virtual implementation for getLocalSubVector().
Ordinal size() const
virtual void acquireDetachedVectorViewImpl(const Range1D &rng, RTOpPack::ConstSubVectorView< Scalar > *sub_vec) const
void getNonconstLocalMultiVectorDataImpl(const Ptr< ArrayRCP< Scalar > > &localValues, const Ptr< Ordinal > &leadingDim)
void getLocalMultiVectorDataImpl(const Ptr< ArrayRCP< const Scalar > > &localValues, const Ptr< Ordinal > &leadingDim) const
#define TEUCHOS_ASSERT(assertion_test)
virtual void acquireNonconstDetachedVectorViewImpl(const Range1D &rng, RTOpPack::SubVectorView< Scalar > *sub_vec)
void releaseDetachedVectorViewImpl(RTOpPack::ConstSubVectorView< Scalar > *sub_vec) const
Implemented through this-&gt;freeLocalData()
Base abstract VectorSpaceBase class for all SPMD-based vector spaces.
virtual Ordinal dim() const =0
Return the dimension of the vector space.
TEUCHOSCORE_LIB_DLL_EXPORT Teuchos::RCP< WorkspaceStore > get_default_workspace_store()
std::string typeName(const T &t)
T * get() const
virtual bool isLocallyReplicated() const =0
Returns true if vector space is locally replicated space.
void acquireNonconstDetachedVectorViewImpl(const Range1D &rng, RTOpPack::SubVectorView< Scalar > *sub_vec)
Implemented through this-&gt;getLocalData()
virtual Ordinal localSubDim() const =0
Returns the number of local elements stored on this process.
void initialize(Ordinal globalOffset_in, Ordinal subDim_in, const ArrayRCP< const Scalar > &values_in, ptrdiff_t stride_in)
virtual void commitNonconstDetachedVectorViewImpl(RTOpPack::SubVectorView< Scalar > *sub_vec)