Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_TpetraVectorSpace_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
43#ifndef THYRA_TPETRA_VECTOR_SPACE_HPP
44#define THYRA_TPETRA_VECTOR_SPACE_HPP
45
46
47#include "Thyra_TpetraVectorSpace_decl.hpp"
48#include "Thyra_TpetraThyraWrappers.hpp"
49#include "Thyra_TpetraVector.hpp"
50#include "Thyra_TpetraMultiVector.hpp"
51#include "Thyra_TpetraEuclideanScalarProd.hpp"
52#include "Tpetra_Details_StaticView.hpp"
53
54namespace Thyra {
55
56
57template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
60{
61 const RCP<this_t> vs(new this_t);
62 vs->weakSelfPtr_ = vs.create_weak();
63 return vs;
64}
65
66
67template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
69 const RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > &tpetraMap
70 )
71{
72 comm_ = convertTpetraToThyraComm(tpetraMap->getComm());
73 tpetraMap_ = tpetraMap;
74 this->updateState(tpetraMap->getGlobalNumElements(),
75 !tpetraMap->isDistributed());
77}
78
79
80// Utility functions
81
82
83template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
87{
89 Tpetra::createLocalMapWithNode<LocalOrdinal,GlobalOrdinal,Node>(
90 size, tpetraMap_->getComm() ) );
91}
92
93
94// Overridden from VectorSpace
95
96
97template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
100{
102 weakSelfPtr_.create_strong().getConst(),
104 new Tpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetraMap_, false)
105 )
106 );
107}
108
109
110template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
113{
115 weakSelfPtr_.create_strong().getConst(),
116 this->createLocallyReplicatedVectorSpace(numMembers),
118 new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(
119 tpetraMap_, numMembers, false)
120 )
121 );
122}
123
124
125template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
126class CopyTpetraMultiVectorViewBack {
127public:
128 CopyTpetraMultiVectorViewBack( RCP<MultiVectorBase<Scalar> > mv, const RTOpPack::SubMultiVectorView<Scalar> &raw_mv )
129 :mv_(mv), raw_mv_(raw_mv)
130 {
131 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv_,true)->getTpetraMultiVector();
132 bool inUse = Teuchos::get_extra_data<bool>(tmv,"inUse");
134 std::runtime_error,
135 "Cannot use the cached vector simultaneously more than once.");
136 inUse = true;
137 Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv), Teuchos::POST_DESTROY, false);
138 }
139 ~CopyTpetraMultiVectorViewBack()
140 {
142 mv_->acquireDetachedView(Range1D(),Range1D(),&smv);
143 RTOpPack::assign_entries<Scalar>( Teuchos::outArg(raw_mv_), smv );
144 mv_->releaseDetachedView(&smv);
145 bool inUse = false;
146 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv_,true)->getTpetraMultiVector();
147 Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv), Teuchos::POST_DESTROY, false);
148 }
149private:
150 RCP<MultiVectorBase<Scalar> > mv_;
151 const RTOpPack::SubMultiVectorView<Scalar> raw_mv_;
152};
153
154
155template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
158 const RTOpPack::SubMultiVectorView<Scalar> &raw_mv ) const
159{
160#ifdef TEUCHOS_DEBUG
161 TEUCHOS_TEST_FOR_EXCEPT( raw_mv.subDim() != this->dim() );
162#endif
163
164 // Create a multi-vector
166 if (!tpetraMap_->isDistributed()) {
167
168 if (tpetraMV_.is_null() || (tpetraMV_->getNumVectors() != size_t (raw_mv.numSubCols()))) {
169 if (!tpetraMV_.is_null())
170 // The MV is already allocated. If we are still using it, then very bad things can happen.
171 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::get_extra_data<bool>(tpetraMV_,"inUse"),
172 std::runtime_error,
173 "Cannot use the cached vector simultaneously more than once.");
174 using IST = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::impl_scalar_type;
175 using DT = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::device_type;
176 auto dv = ::Tpetra::Details::getStatic2dDualView<IST, DT> (tpetraMap_->getGlobalNumElements(), raw_mv.numSubCols());
177 tpetraMV_ = Teuchos::rcp(new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetraMap_, dv));
178 bool inUse = false;
179 Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tpetraMV_));
180 }
181
182 if (tpetraDomainSpace_.is_null() || raw_mv.numSubCols() != tpetraDomainSpace_->localSubDim())
183 tpetraDomainSpace_ = tpetraVectorSpace<Scalar>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(raw_mv.numSubCols(), tpetraMap_->getComm()));
184
185 mv = tpetraMultiVector<Scalar>(weakSelfPtr_.create_strong().getConst(), tpetraDomainSpace_, tpetraMV_);
186 } else {
187 mv = this->createMembers(raw_mv.numSubCols());
188 bool inUse = false;
189 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv,true)->getTpetraMultiVector();
190 Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv));
191 }
192 // Copy initial values in raw_mv into multi-vector
194 mv->acquireDetachedView(Range1D(),Range1D(),&smv);
195 RTOpPack::assign_entries<Scalar>(
196 Ptr<const RTOpPack::SubMultiVectorView<Scalar> >(Teuchos::outArg(smv)),
197 raw_mv
198 );
199 mv->commitDetachedView(&smv);
200 // Setup smart pointer to multi-vector to copy view back out just before multi-vector is destroyed
201 Teuchos::set_extra_data(
202 // We create a duplicate of the RCP, otherwise the ref count does not go to zero.
203 Teuchos::rcp(new CopyTpetraMultiVectorViewBack<Scalar,LocalOrdinal,GlobalOrdinal,Node>(Teuchos::rcpFromRef(*mv),raw_mv)),
204 "CopyTpetraMultiVectorViewBack",
205 Teuchos::outArg(mv),
206 Teuchos::PRE_DESTROY
207 );
208 return mv;
209}
210
211
212template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
216{
217#ifdef TEUCHOS_DEBUG
218 TEUCHOS_TEST_FOR_EXCEPT( raw_mv.subDim() != this->dim() );
219#endif
220 // Create a multi-vector
222 if (!tpetraMap_->isDistributed()) {
223 if (tpetraMV_.is_null() || (tpetraMV_->getNumVectors() != size_t (raw_mv.numSubCols()))) {
224 if (!tpetraMV_.is_null())
225 // The MV is already allocated. If we are still using it, then very bad things can happen.
226 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::get_extra_data<bool>(tpetraMV_,"inUse"),
227 std::runtime_error,
228 "Cannot use the cached vector simultaneously more than once.");
229 using IST = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::impl_scalar_type;
230 using DT = typename Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::device_type;
231 auto dv = ::Tpetra::Details::getStatic2dDualView<IST, DT> (tpetraMap_->getGlobalNumElements(), raw_mv.numSubCols());
232 tpetraMV_ = Teuchos::rcp(new Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetraMap_, dv));
233 bool inUse = false;
234 Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tpetraMV_));
235 }
236
237 if (tpetraDomainSpace_.is_null() || raw_mv.numSubCols() != tpetraDomainSpace_->localSubDim())
238 tpetraDomainSpace_ = tpetraVectorSpace<Scalar>(Tpetra::createLocalMapWithNode<LocalOrdinal, GlobalOrdinal, Node>(raw_mv.numSubCols(), tpetraMap_->getComm()));
239
240 mv = tpetraMultiVector<Scalar>(weakSelfPtr_.create_strong().getConst(), tpetraDomainSpace_, tpetraMV_);
241 } else {
242 mv = this->createMembers(raw_mv.numSubCols());
243 bool inUse = false;
244 RCP<Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tmv = Teuchos::rcp_dynamic_cast<TpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(mv,true)->getTpetraMultiVector();
245 Teuchos::set_extra_data(inUse,"inUse",Teuchos::outArg(tmv));
246 }
247 // Copy values in raw_mv into multi-vector
249 mv->acquireDetachedView(Range1D(),Range1D(),&smv);
250 RTOpPack::assign_entries<Scalar>(
251 Ptr<const RTOpPack::SubMultiVectorView<Scalar> >(Teuchos::outArg(smv)),
252 raw_mv );
253 mv->commitDetachedView(&smv);
254 return mv;
255}
256
257
258template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
260 const Range1D& rng_in, const EViewType viewType, const EStrideType strideType
261 ) const
262{
263 const Range1D rng = full_range(rng_in,0,this->dim()-1);
264 const Ordinal l_localOffset = this->localOffset();
265
266 const Ordinal myLocalSubDim = tpetraMap_.is_null () ?
267 static_cast<Ordinal> (0) : tpetraMap_->getLocalNumElements ();
268
269 return ( l_localOffset<=rng.lbound() && rng.ubound()<l_localOffset+myLocalSubDim );
270}
271
272
273template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
279
280template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
286
287// Overridden from SpmdVectorSpaceDefaultBase
288
289
290template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
296
297
298template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
300{
301 return tpetraMap_.is_null () ? static_cast<Ordinal> (0) :
302 static_cast<Ordinal> (tpetraMap_->getLocalNumElements ());
303}
304
305// private
306
307
308template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
309TpetraVectorSpace<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TpetraVectorSpace()
310{
311 // The base classes should automatically default initialize to a safe
312 // uninitialized state.
313}
314
315
316} // end namespace Thyra
317
318
319#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< MultiVectorBase< Scalar > > createCachedMembersView(const RTOpPack::SubMultiVectorView< Scalar > &raw_mv) const
Create a (possibly) cached multi-vector member that is a non-const view of raw multi-vector data....
RCP< const VectorSpaceBase< Scalar > > clone() const
RCP< VectorBase< Scalar > > createMember() const
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)