Thyra Version of the Day
Loading...
Searching...
No Matches
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
21namespace Thyra {
22
23
24template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
25RCP<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
34template <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
50template <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
64template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
67{
68 return tpetraVector<Scalar>(
69 weakSelfPtr_.create_strong().getConst(),
71 new Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetraMap_, false)
72 )
73 );
74}
75
76
77template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
80{
81 return tpetraMultiVector<Scalar>(
82 weakSelfPtr_.create_strong().getConst(),
83 this->createLocallyReplicatedVectorSpace(numMembers),
85 new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(
86 tpetraMap_, numMembers, false)
87 )
88 );
89}
90
91
92template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
93class CopyTpetraMultiVectorViewBack {
94public:
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 }
116private:
117 RCP<MultiVectorBase<Scalar> > mv_;
119};
120
121
122template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123RCP< 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.
140 std::runtime_error,
141 "Cannot use the cached vector simultaneously more than once.");
142 using IST = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::impl_scalar_type;
143 using DT = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::device_type;
144 auto dv = ::Tpetra::Details::getStatic2dDualView<IST, DT> (tpetraMap_->getGlobalNumElements(), raw_mv.numSubCols());
145 tpetraMV_ = Teuchos::rcp(new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetraMap_, dv));
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),
177 );
178 return mv;
179}
180
181
182template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
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.
197 std::runtime_error,
198 "Cannot use the cached vector simultaneously more than once.");
199 using IST = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::impl_scalar_type;
200 using DT = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::device_type;
201 auto dv = ::Tpetra::Details::getStatic2dDualView<IST, DT> (tpetraMap_->getGlobalNumElements(), raw_mv.numSubCols());
202 tpetraMV_ = Teuchos::rcp(new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetraMap_, dv));
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
228template <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
243template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
246{
247 return tpetraVectorSpace<Scalar>(tpetraMap_);
248}
249
250template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
256
257// Overridden from SpmdVectorSpaceDefaultBase
258
259
260template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
266
267
268template <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
278template <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
RCP< T > create_weak() const
bool is_null() const
Ordinal lbound() const
Ordinal ubound() const
Interface for a collection of column vectors called a multi-vector.
Concrete implementation of an SPMD vector space for Tpetra.
RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > getTpetraMap() const
Get the embedded Tpetra::Map.
bool hasInCoreView(const Range1D &rng, const EViewType viewType, const EStrideType strideType) const
Returns true if all the elements in rng are in this process.
void initialize(const RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &tpetraMap)
Initialize a serial space.
RCP< const VectorSpaceBase< Scalar > > clone() const
RCP< VectorBase< Scalar > > createMember() 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....
RCP< MultiVectorBase< Scalar > > createMembers(int numMembers) const
RCP< const Teuchos::Comm< Ordinal > > getComm() const
static RCP< TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > > create()
Create with weak ownership to self.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
EStrideType
Determine if data is unit stride or non-unit stride.
EViewType
Determines if a view is a direct view of data or a detached copy of data.
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
Teuchos::Range1D Range1D
RCP< const Teuchos::Comm< Ordinal > > convertTpetraToThyraComm(const RCP< const Teuchos::Comm< int > > &tpetraComm)
Given an Tpetra Teuchos::Comm<int> object, return an equivalent Teuchos::Comm<Ordinal> object.
T_To & dyn_cast(T_From &from)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)