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>
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());
44}
45
46
47// Utility functions
48
49
50template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
54{
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{
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{
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 {
98 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv_,true)->getTpetraMultiVector();
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_;
118 const RTOpPack::SubMultiVectorView<Scalar> raw_mv_;
119};
120
121
122template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
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.");
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;
157 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv,true)->getTpetraMultiVector();
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
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.
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.");
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;
214 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv,true)->getTpetraMultiVector();
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>
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>
279TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TpetraVectorSpace()
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.
virtual void setScalarProd(const RCP< const ScalarProdBase< Scalar > > &scalarProd)
Set a different scalar product.
virtual void updateState(const Ordinal globalDim, const bool isLocallyReplicated=false)
This function must be called whenever the state of this changes and some internal state must be updat...
Ordinal dim() const
Returns the sum of the local number of elements on every process.
RCP< const TpetraEuclideanScalarProd< Scalar, LocalOrdinal, GlobalOrdinal, Node > > tpetraEuclideanScalarProd()
Nonmember constructor for TpetraEuclideanScalarProd.
RCP< TpetraMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > tpetraMultiVector(const RCP< const TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraVectorSpace, const RCP< const ScalarProdVectorSpaceBase< Scalar > > &domainSpace, const RCP< Tpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraMultiVector)
Nonmember constructor for non-const TpetraMultiVector.
Concrete implementation of an SPMD vector space for Tpetra.
TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > this_t
RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > getTpetraMap() const
Get the embedded Tpetra::Map.
RCP< TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > > tpetraVectorSpace(const RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &tpetraMap)
Nonmember constructor that creats a serial vector space.
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.
RCP< TpetraVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > tpetraVector(const RCP< const TpetraVectorSpace< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraVectorSpace, const RCP< Tpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &tpetraVector)
Nonmember constructor for TpetraVector.
#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::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.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)