Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_TpetraVectorSpace_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_TPETRA_VECTOR_SPACE_HPP
11 #define THYRA_TPETRA_VECTOR_SPACE_HPP
12 
13 
14 #include "Thyra_TpetraVectorSpace_decl.hpp"
15 #include "Thyra_TpetraThyraWrappers.hpp"
16 #include "Thyra_TpetraVector.hpp"
17 #include "Thyra_TpetraMultiVector.hpp"
18 #include "Thyra_TpetraEuclideanScalarProd.hpp"
19 #include "Tpetra_Details_StaticView.hpp"
20 
21 namespace Thyra {
22 
23 
24 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
25 RCP<TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
27 {
28  const RCP<this_t> vs(new this_t);
29  vs->weakSelfPtr_ = vs.create_weak();
30  return vs;
31 }
32 
33 
34 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
36  const RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > &tpetraMap
37  )
38 {
39  comm_ = convertTpetraToThyraComm(tpetraMap->getComm());
40  tpetraMap_ = tpetraMap;
41  this->updateState(tpetraMap->getGlobalNumElements(),
42  !tpetraMap->isDistributed());
43  this->setScalarProd(tpetraEuclideanScalarProd<Scalar,LocalOrdinal,GlobalOrdinal,Node>());
44 }
45 
46 
47 // Utility functions
48 
49 
50 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
54 {
55  return tpetraVectorSpace<Scalar>(
56  Tpetra::createLocalMapWithNode<LocalOrdinal,GlobalOrdinal,Node>(
57  size, tpetraMap_->getComm() ) );
58 }
59 
60 
61 // Overridden from VectorSpace
62 
63 
64 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
67 {
68  return tpetraVector<Scalar>(
69  weakSelfPtr_.create_strong().getConst(),
72  )
73  );
74 }
75 
76 
77 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
80 {
81  return tpetraMultiVector<Scalar>(
82  weakSelfPtr_.create_strong().getConst(),
83  this->createLocallyReplicatedVectorSpace(numMembers),
86  tpetraMap_, numMembers, false)
87  )
88  );
89 }
90 
91 
92 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
93 class CopyTpetraMultiVectorViewBack {
94 public:
95  CopyTpetraMultiVectorViewBack( RCP<MultiVectorBase<Scalar> > mv, const RTOpPack::SubMultiVectorView<Scalar> &raw_mv )
96  :mv_(mv), raw_mv_(raw_mv)
97  {
99  bool inUse = Teuchos::get_extra_data<bool>(tmv,"inUse");
101  std::runtime_error,
102  "Cannot use the cached vector simultaneously more than once.");
103  inUse = true;
104  Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv), Teuchos::POST_DESTROY, false);
105  }
106  ~CopyTpetraMultiVectorViewBack()
107  {
109  mv_->acquireDetachedView(Range1D(),Range1D(),&smv);
110  RTOpPack::assign_entries<Scalar>( Teuchos::outArg(raw_mv_), smv );
111  mv_->releaseDetachedView(&smv);
112  bool inUse = false;
113  RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv_,true)->getTpetraMultiVector();
114  Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv), Teuchos::POST_DESTROY, false);
115  }
116 private:
117  RCP<MultiVectorBase<Scalar> > mv_;
119 };
120 
121 
122 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123 RCP< MultiVectorBase<Scalar> >
126  const bool initialize) const
127 {
128 #ifdef TEUCHOS_DEBUG
129  TEUCHOS_TEST_FOR_EXCEPT( raw_mv.subDim() != this->dim() );
130 #endif
131 
132  // Create a multi-vector
134  if (!tpetraMap_->isDistributed()) {
135 
136  if (tpetraMV_.is_null() || (tpetraMV_->getNumVectors() != size_t (raw_mv.numSubCols()))) {
137  if (!tpetraMV_.is_null())
138  // The MV is already allocated. If we are still using it, then very bad things can happen.
139  TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::get_extra_data<bool>(tpetraMV_,"inUse"),
140  std::runtime_error,
141  "Cannot use the cached vector simultaneously more than once.");
144  auto dv = ::Tpetra::Details::getStatic2dDualView<IST, DT> (tpetraMap_->getGlobalNumElements(), raw_mv.numSubCols());
146  bool inUse = false;
147  Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tpetraMV_));
148  }
149 
150  if (tpetraDomainSpace_.is_null() || raw_mv.numSubCols() != tpetraDomainSpace_->localSubDim())
151  tpetraDomainSpace_ = tpetraVectorSpace<Scalar>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(raw_mv.numSubCols(), tpetraMap_->getComm()));
152 
153  mv = tpetraMultiVector<Scalar>(weakSelfPtr_.create_strong().getConst(), tpetraDomainSpace_, tpetraMV_);
154  } else {
155  mv = this->createMembers(raw_mv.numSubCols());
156  bool inUse = false;
158  Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv));
159  }
160  if (initialize) {
161  // Copy initial values in raw_mv into multi-vector
163  mv->acquireDetachedView(Range1D(),Range1D(),&smv);
164  RTOpPack::assign_entries<Scalar>(
165  Ptr<const RTOpPack::SubMultiVectorView<Scalar> >(Teuchos::outArg(smv)),
166  raw_mv
167  );
168  mv->commitDetachedView(&smv);
169  }
170  // Setup smart pointer to multi-vector to copy view back out just before multi-vector is destroyed
171  Teuchos::set_extra_data(
172  // We create a duplicate of the RCP, otherwise the ref count does not go to zero.
173  Teuchos::rcp(new CopyTpetraMultiVectorViewBack<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcpFromRef(*mv),raw_mv)),
174  "CopyTpetraMultiVectorViewBack",
175  Teuchos::outArg(mv),
176  Teuchos::PRE_DESTROY
177  );
178  return mv;
179 }
180 
181 
182 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
185  const RTOpPack::ConstSubMultiVectorView<Scalar> &raw_mv ) const
186 {
187 #ifdef TEUCHOS_DEBUG
188  TEUCHOS_TEST_FOR_EXCEPT( raw_mv.subDim() != this->dim() );
189 #endif
190  // Create a multi-vector
192  if (!tpetraMap_->isDistributed()) {
193  if (tpetraMV_.is_null() || (tpetraMV_->getNumVectors() != size_t (raw_mv.numSubCols()))) {
194  if (!tpetraMV_.is_null())
195  // The MV is already allocated. If we are still using it, then very bad things can happen.
196  TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::get_extra_data<bool>(tpetraMV_,"inUse"),
197  std::runtime_error,
198  "Cannot use the cached vector simultaneously more than once.");
201  auto dv = ::Tpetra::Details::getStatic2dDualView<IST, DT> (tpetraMap_->getGlobalNumElements(), raw_mv.numSubCols());
203  bool inUse = false;
204  Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tpetraMV_));
205  }
206 
207  if (tpetraDomainSpace_.is_null() || raw_mv.numSubCols() != tpetraDomainSpace_->localSubDim())
208  tpetraDomainSpace_ = tpetraVectorSpace<Scalar>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(raw_mv.numSubCols(), tpetraMap_->getComm()));
209 
210  mv = tpetraMultiVector<Scalar>(weakSelfPtr_.create_strong().getConst(), tpetraDomainSpace_, tpetraMV_);
211  } else {
212  mv = this->createMembers(raw_mv.numSubCols());
213  bool inUse = false;
215  Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv));
216  }
217  // Copy values in raw_mv into multi-vector
219  mv->acquireDetachedView(Range1D(),Range1D(),&smv);
220  RTOpPack::assign_entries<Scalar>(
221  Ptr<const RTOpPack::SubMultiVectorView<Scalar> >(Teuchos::outArg(smv)),
222  raw_mv );
223  mv->commitDetachedView(&smv);
224  return mv;
225 }
226 
227 
228 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
230  const Range1D& rng_in, const EViewType viewType, const EStrideType strideType
231  ) const
232 {
233  const Range1D rng = full_range(rng_in,0,this->dim()-1);
234  const Ordinal l_localOffset = this->localOffset();
235 
236  const Ordinal myLocalSubDim = tpetraMap_.is_null () ?
237  static_cast<Ordinal> (0) : tpetraMap_->getLocalNumElements ();
238 
239  return ( l_localOffset<=rng.lbound() && rng.ubound()<l_localOffset+myLocalSubDim );
240 }
241 
242 
243 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
246 {
247  return tpetraVectorSpace<Scalar>(tpetraMap_);
248 }
249 
250 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
253 {
254  return tpetraMap_;
255 }
256 
257 // Overridden from SpmdVectorSpaceDefaultBase
258 
259 
260 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
263 {
264  return comm_;
265 }
266 
267 
268 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
270 {
271  return tpetraMap_.is_null () ? static_cast<Ordinal> (0) :
272  static_cast<Ordinal> (tpetraMap_->getLocalNumElements ());
273 }
274 
275 // private
276 
277 
278 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
280 {
281  // The base classes should automatically default initialize to a safe
282  // uninitialized state.
283 }
284 
285 
286 } // end namespace Thyra
287 
288 
289 #endif // THYRA_TPETRA_VECTOR_SPACE_HPP
Concrete implementation of Thyra::MultiVector in terms of Tpetra::MultiVector.
Concrete implementation of an SPMD vector space for Tpetra.
RCP< const VectorSpaceBase< Scalar > > clone() const
RCP< T > create_weak() const
typename map_type::device_type device_type
RCP< TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > > createLocallyReplicatedVectorSpace(int size) const
Create Tpetra locally replicated vector space.
static RCP< TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > > create()
Create with weak ownership to self.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void initialize(const RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &tpetraMap)
Initialize a serial space.
EViewType
Determines if a view is a direct view of data or a detached copy of data.
Ordinal ubound() const
typename Kokkos::ArithTraits< Scalar >::val_type impl_scalar_type
RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > getTpetraMap() const
Get the embedded Tpetra::Map.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
Interface for a collection of column vectors called a multi-vector.
bool hasInCoreView(const Range1D &rng, const EViewType viewType, const EStrideType strideType) const
Returns true if all the elements in rng are in this process.
RCP< const Teuchos::Comm< Ordinal > > convertTpetraToThyraComm(const RCP< const Teuchos::Comm< int > > &tpetraComm)
Given an Tpetra Teuchos::Comm&lt;int&gt; object, return an equivalent Teuchos::Comm&lt;Ordinal&gt; object...
RCP< VectorBase< Scalar > > createMember() const
Ordinal lbound() const
RCP< MultiVectorBase< Scalar > > createMembers(int numMembers) const
EStrideType
Determine if data is unit stride or non-unit stride.
RCP< const Teuchos::Comm< Ordinal > > getComm() const
RCP< MultiVectorBase< Scalar > > createCachedMembersView(const RTOpPack::SubMultiVectorView< Scalar > &raw_mv, bool initialize=true) const
Create a (possibly) cached multi-vector member that is a non-const view of raw multi-vector data...
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
Teuchos::Range1D Range1D