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 //
4 // Thyra: Interfaces and Support for Abstract Numerical Algorithms
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef THYRA_SPMD_VECTOR_DEFAULT_BASE_DEF_HPP
43 #define THYRA_SPMD_VECTOR_DEFAULT_BASE_DEF_HPP
44 
45 // disable clang warnings
46 #if defined (__clang__) && !defined (__INTEL_COMPILER)
47 #pragma clang system_header
48 #endif
49 
50 #include "Thyra_SpmdVectorDefaultBase_decl.hpp"
51 #include "Thyra_VectorDefaultBase.hpp"
52 #include "Thyra_SpmdVectorSpaceDefaultBase.hpp"
53 #include "Thyra_apply_op_helper.hpp"
54 #include "Thyra_SpmdLocalDataAccess.hpp"
55 #include "RTOpPack_SPMD_apply_op.hpp"
56 #include "Teuchos_Workspace.hpp"
57 #include "Teuchos_Assert.hpp"
58 #include "Teuchos_dyn_cast.hpp"
59 #include "Teuchos_Assert.hpp"
60 
61 
62 namespace Thyra {
63 
64 
65 // Public interface functions
66 
67 
68 template<class Scalar>
70  :globalDim_(0)
71  ,localOffset_(-1)
72  ,localSubDim_(0)
73 {}
74 
75 
76 template<class Scalar>
78  const Ptr<const Teuchos::Comm<Ordinal> > &comm_in,
79  const RTOpPack::RTOpT<Scalar> &op,
80  const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
81  const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
82  const Ptr<RTOpPack::ReductTarget> &reduct_obj,
83  const Ordinal global_offset_in
84  ) const
85 {
86 
87  using Teuchos::null;
88  using Teuchos::dyn_cast;
89  using Teuchos::Workspace;
90  using Teuchos::rcpFromPtr;
91 
92  const int num_vecs = vecs.size();
93  const int num_targ_vecs = targ_vecs.size();
94 
96  const SpmdVectorSpaceBase<Scalar> &spmdSpc = *this->spmdSpace();
97 
98 #ifdef TEUCHOS_DEBUG
100  "SpmdVectorDefaultBase<>::applyOp(...)",*space(),
101  op, vecs, targ_vecs, reduct_obj, global_offset_in);
102 #endif
103 
105  if (nonnull(comm_in))
106  comm = Teuchos::rcpFromPtr(comm_in);
107  else
108  comm = spmdSpc.getComm();
109 
110  // First see if this is a locally replicated vector in which case
111  // we treat this as a local operation only.
112  const bool locallyReplicated = spmdSpc.isLocallyReplicated();
113 
114  const Range1D local_rng(localOffset_, localOffset_+localSubDim_-1);
115 
116  // Create sub-vector views of all of the *participating* local data
117  Workspace<RTOpPack::ConstSubVectorView<Scalar> > sub_vecs(wss.get(), num_vecs);
118  Workspace<RTOpPack::SubVectorView<Scalar> > sub_targ_vecs(wss.get(), num_targ_vecs);
119  for(int k = 0; k < num_vecs; ++k ) {
120  sub_vecs[k] = getLocalSubVectorView<Scalar>(rcpFromPtr(vecs[k]));
121  sub_vecs[k].setGlobalOffset(localOffset_+global_offset_in);
122  }
123  for(int k = 0; k < num_targ_vecs; ++k ) {
124  sub_targ_vecs[k] = getNonconstLocalSubVectorView<Scalar>(rcpFromPtr(targ_vecs[k]));
125  sub_targ_vecs[k].setGlobalOffset(localOffset_+global_offset_in);
126  }
127 
128  // Apply the RTOp operator object (all processors must participate)
129  RTOpPack::SPMD_apply_op(
130  locallyReplicated ? NULL : &*comm, // comm
131  op, // op
132  num_vecs, // num_vecs
133  sub_vecs.getRawPtr(), // sub_vecs
134  num_targ_vecs, // num_targ_vecs
135  sub_targ_vecs.getRawPtr(), // targ_sub_vecs
136  reduct_obj.get() // reduct_obj
137  );
138 
139  // Free and commit the local data
140  for (int k = 0; k < num_vecs; ++k ) {
141  sub_vecs[k] = RTOpPack::ConstSubVectorView<Scalar>();
142  }
143  for (int k = 0; k < num_targ_vecs; ++k ) {
144  sub_targ_vecs[k] = RTOpPack::SubVectorView<Scalar>();
145  }
146 
147 }
148 
149 
150 // Overridden from Teuchos::Describable
151 
152 
153 template<class Scalar>
155 {
156  using Teuchos::RCP; using Teuchos::Comm; using Teuchos::null;
157  using Teuchos::typeName;
158  std::ostringstream ostr;
159  ostr<<typeName(*this)<<"{spmdSpace="<<this->spmdSpace()->description()<<"}";
160  return ostr.str();
161 }
162 
163 
164 // Overridden public functions from VectorBase
165 
166 
167 template<class Scalar>
170 {
171  return this->spmdSpace();
172 }
173 
174 
175 // protected
176 
177 
178 // Overridden protected functions from VectorBase
179 
180 
181 template<class Scalar>
183  const RTOpPack::RTOpT<Scalar> &op,
184  const ArrayView<const Ptr<const VectorBase<Scalar> > > &vecs,
185  const ArrayView<const Ptr<VectorBase<Scalar> > > &targ_vecs,
186  const Ptr<RTOpPack::ReductTarget> &reduct_obj,
187  const Ordinal global_offset
188  ) const
189 {
190  applyOpImplWithComm( Teuchos::null, op, vecs, targ_vecs, reduct_obj,
191  global_offset);
192 }
193 
194 
195 template<class Scalar>
197  const Range1D& rng_in, RTOpPack::ConstSubVectorView<Scalar>* sub_vec
198  ) const
199 {
200 #ifdef THYRA_DEBUG
201  TEUCHOS_ASSERT(sub_vec);
202 #endif
203  if( rng_in == Range1D::Invalid ) {
204  // Just return an null view
206  return;
207  }
208  const bool isFullRng = rng_in.full_range();
209  const Range1D rng = validateRange(rng_in);
210  const bool isLocallyReplicated = this->spmdSpace()->isLocallyReplicated();
211  if (
212  (
213  rng.lbound() < localOffset_
214  ||
215  localOffset_+localSubDim_-1 < rng.ubound()
216  ||
217  isFullRng
218  )
219  &&
220  !isLocallyReplicated
221  )
222  {
223  // rng consists of off-processor elements so use the default implementation!
225  return;
226  }
227  // rng consists of all local data so get it!
228  ArrayRCP<const Scalar>localValues;
229  this->getLocalData(Teuchos::outArg(localValues));
230  sub_vec->initialize(
231  rng.lbound(), // globalOffset
232  rng.size(), // subDim
233  localValues.persistingView(rng.lbound()-localOffset_, rng.size()),
234  1 // stride
235  );
236 }
237 
238 
239 template<class Scalar>
242  ) const
243 {
244 #ifdef TEUCHOS_DEBUG
246  sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
247  ,std::logic_error
248  ,"SpmdVectorDefaultBase<Scalar>::releaseDetachedVectorViewImpl(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
249  );
250 #endif
251  if(
252  sub_vec->globalOffset() < localOffset_
253  || localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
254  )
255  {
256  // Let the default implementation handle it!
258  return;
259  }
260  // Nothing to deallocate!
261  sub_vec->uninitialize();
262 }
263 
264 
265 template<class Scalar>
267  const Range1D& rng_in, RTOpPack::SubVectorView<Scalar>* sub_vec
268  )
269 {
270 #ifdef THYRA_DEBUG
271  TEUCHOS_ASSERT(sub_vec);
272 #endif
273  if( rng_in == Range1D::Invalid ) {
274  // Just return an null view
275  *sub_vec = RTOpPack::SubVectorView<Scalar>();
276  return;
277  }
278  const bool isFullRng = rng_in.full_range();
279  const Range1D rng = validateRange(rng_in);
280  const bool isLocallyReplicated = this->spmdSpace()->isLocallyReplicated();
281  if (
282  (
283  rng.lbound() < localOffset_
284  ||
285  localOffset_+localSubDim_-1 < rng.ubound()
286  ||
287  isFullRng
288  )
289  &&
290  !isLocallyReplicated
291  )
292  {
293  // rng consists of off-processor elements so use the default implementation!
295  return;
296  }
297  // rng consists of all local data so get it!
298  ArrayRCP<Scalar> localValues;
299  this->getNonconstLocalData(Teuchos::outArg(localValues));
300  sub_vec->initialize(
301  rng.lbound(), // globalOffset
302  rng.size(), // subDim
303  localValues.persistingView(rng.lbound()-localOffset_, rng.size()),
304  1 // stride
305  );
306 }
307 
308 
309 template<class Scalar>
312  )
313 {
314 #ifdef TEUCHOS_DEBUG
316  sub_vec==NULL || sub_vec->globalOffset() < 0 || sub_vec->globalOffset() + sub_vec->subDim() > globalDim_
317  ,std::logic_error
318  ,"SpmdVectorDefaultBase<Scalar>::commitDetachedView(...) : Error, this sub vector was not gotten from acquireDetachedView(...)!"
319  );
320 #endif
321  if(
322  sub_vec->globalOffset() < localOffset_
323  ||
324  localOffset_+localSubDim_ < sub_vec->globalOffset()+sub_vec->subDim()
325  )
326  {
327  // Let the default implementation handle it!
329  return;
330  }
331  sub_vec->uninitialize(); // Nothing to deallocate!
332 }
333 
334 
335 // Overridden Protected functions from SpmdMultiVectorBase
336 
337 
338 template<class Scalar>
341 {
342  ArrayRCP<Scalar> localValues;
343  this->getNonconstLocalData(Teuchos::outArg(localValues));
345  localOffset_, // globalOffset
346  localSubDim_,
347  0, // colOffset
348  1, // numCols
349  localValues,
350  localSubDim_ // leadingDim
351  );
352 }
353 
354 
355 template<class Scalar>
358 {
359  using Teuchos::outArg;
360  ArrayRCP<const Scalar> localValues;
361  this->getLocalData(outArg(localValues));
363  localOffset_, // globalOffset
364  localSubDim_,
365  0, // colOffset
366  1, // numCols
367  localValues,
368  localSubDim_ // leadingDim
369  );
370 }
371 
372 
373 template<class Scalar>
375  const Ptr<ArrayRCP<Scalar> > &localValues, const Ptr<Ordinal> &leadingDim)
376 {
377  this->getNonconstLocalData(localValues);
378  *leadingDim = localValues->size();
379 }
380 
381 
382 template<class Scalar>
384  const Ptr<ArrayRCP<const Scalar> > &localValues, const Ptr<Ordinal> &leadingDim) const
385 {
386  this->getLocalData(localValues);
387  *leadingDim = localValues->size();
388 }
389 
390 
391 // Overridden Protected functions from SpmdVectorBase
392 
393 
394 template<class Scalar>
397 {
398  ArrayRCP<Scalar> localValues;
399  this->getNonconstLocalData(Teuchos::outArg(localValues));
401  localOffset_,
402  localSubDim_,
403  localValues,
404  1 // stride
405  );
406 }
407 
408 
409 template<class Scalar>
412 {
413  ArrayRCP<const Scalar> localValues;
414  this->getLocalData(Teuchos::outArg(localValues));
416  localOffset_, // globalOffset?
417  localSubDim_,
418  localValues,
419  1 // stride
420  );
421 }
422 
423 
424 // Protected functions to be used by subclasses
425 
426 
427 template<class Scalar>
429 {
430  if(globalDim_ == 0) {
431  const SpmdVectorSpaceBase<Scalar> *l_spmdSpace = this->spmdSpace().get();
432  if(l_spmdSpace) {
433  globalDim_ = l_spmdSpace->dim();
434  localOffset_ = l_spmdSpace->localOffset();
435  localSubDim_ = l_spmdSpace->localSubDim();
436  }
437  else {
438  globalDim_ = 0;
439  localOffset_ = -1;
440  localSubDim_ = 0;
441  }
442  }
443 }
444 
445 
446 // private
447 
448 
449 template<class Scalar>
451 {
452  const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
453 #ifdef TEUCHOS_DEBUG
455  !(0 <= rng.lbound() && rng.ubound() < globalDim_), std::invalid_argument
456  ,"SpmdVectorDefaultBase<Scalar>::validateRange(...): Error, the range ["
457  <<rng.lbound()<<","<<rng.ubound()<<"] is not "
458  "in the range [0,"<<(globalDim_-1)<<"]!"
459  );
460 #endif
461  return rng;
462 }
463 
464 
465 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
466 template<class Scalar>
467 bool SpmdVectorDefaultBase<Scalar>::show_dump = false;
468 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
469 
470 
471 } // end namespace Thyra
472 
473 
474 #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().
static const Range1D Invalid
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)