Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_MultiVectorLinearOp.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ****************************************************************************
3 // Tempus: Copyright (2017) Sandia Corporation
4 //
5 // Distributed under BSD 3-clause license (See accompanying file Copyright.txt)
6 // ****************************************************************************
7 // @HEADER
8 
9 #ifndef Thyra_MultiVectorLinearOp_hpp
10 #define Thyra_MultiVectorLinearOp_hpp
11 
12 #include "Thyra_RowStatLinearOpBase.hpp"
13 #include "Thyra_ScaledLinearOpBase.hpp"
14 #include "Thyra_DefaultMultiVectorProductVectorSpace.hpp"
15 #include "Thyra_DefaultMultiVectorProductVector.hpp"
16 #include "Teuchos_ConstNonconstObjectContainer.hpp"
17 #include "Thyra_VectorStdOps.hpp"
18 #include "Thyra_MultiVectorStdOps.hpp"
19 #include "Thyra_AssertOp.hpp"
20 #include "Teuchos_dyn_cast.hpp"
21 
22 namespace Thyra {
23 
28 template <class Scalar>
29 class MultiVectorLinearOp : virtual public RowStatLinearOpBase<Scalar>,
30  virtual public ScaledLinearOpBase<Scalar> {
31  public:
34 
37 
39  const RCP<LinearOpBase<Scalar> > &op,
41  &multiVecRange,
43  &multiVecDomain)
44  {
45  validateInitialize(op, multiVecRange, multiVecDomain);
46  op_ = op;
47  multiVecRange_ = multiVecRange;
48  multiVecDomain_ = multiVecDomain;
49  }
50 
51  void initialize(const RCP<const LinearOpBase<Scalar> > &op,
53  &multiVecRange,
55  &multiVecDomain)
56  {
57  validateInitialize(op, multiVecRange, multiVecDomain);
58  op_ = op;
59  multiVecRange_ = multiVecRange;
60  multiVecDomain_ = multiVecDomain;
61  }
62 
63  RCP<LinearOpBase<Scalar> > getNonconstLinearOp()
64  {
65  return op_.getNonconstObj();
66  }
67 
68  RCP<const LinearOpBase<Scalar> > getLinearOp() const
69  {
70  return op_.getConstObj();
71  }
72 
73  void uninitialize()
74  {
75  op_.uninitialize();
76  multiVecRange_ = Teuchos::null;
77  multiVecDomain_ = Teuchos::null;
78  }
79 
81 
84 
85  RCP<const VectorSpaceBase<Scalar> > range() const { return multiVecRange_; }
86 
87  RCP<const VectorSpaceBase<Scalar> > domain() const { return multiVecDomain_; }
88 
89  RCP<const LinearOpBase<Scalar> > clone() const
90  {
91  return Teuchos::null; // ToDo: Implement if needed ???
92  }
94 
95  protected:
98  bool opSupportedImpl(EOpTransp M_trans) const
99  {
100  return Thyra::opSupported(*op_.getConstObj(), M_trans);
101  }
102 
103  void applyImpl(const EOpTransp M_trans, const MultiVectorBase<Scalar> &XX,
104  const Ptr<MultiVectorBase<Scalar> > &YY, const Scalar alpha,
105  const Scalar beta) const
106  {
107  using Teuchos::dyn_cast;
109 
110  const Ordinal numCols = XX.domain()->dim();
111 
112  for (Ordinal col_j = 0; col_j < numCols; ++col_j) {
113  const RCP<const VectorBase<Scalar> > x = XX.col(col_j);
114  const RCP<VectorBase<Scalar> > y = YY->col(col_j);
115 
116  RCP<const MultiVectorBase<Scalar> > X =
117  dyn_cast<const MVPV>(*x).getMultiVector().assert_not_null();
118  RCP<MultiVectorBase<Scalar> > Y =
119  dyn_cast<MVPV>(*y).getNonconstMultiVector().assert_not_null();
120 
121  Thyra::apply(*op_.getConstObj(), M_trans, *X, Y.ptr(), alpha, beta);
122  }
123  }
125 
128 
131  const RowStatLinearOpBaseUtils::ERowStat rowStat) const
132  {
133  using Teuchos::rcp_dynamic_cast;
134  return rcp_dynamic_cast<const RowStatLinearOpBase<Scalar> >(
135  op_.getConstObj())
136  ->rowStatIsSupported(rowStat);
137  }
138 
143  void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat,
144  const Ptr<VectorBase<Scalar> > &rowStatVec) const
145  {
146  TEUCHOS_ASSERT(this->rowStatIsSupported(rowStat));
147 
148  // Compute the scaling vector from the underlying operator and assign
149  // it to each column of the scaling multivector. We only use the first
150  // column in the scaling below, but this makes the scaling vector
151  // consistent with a Kronecker-product operator
153  using Teuchos::dyn_cast;
154  using Teuchos::rcp_dynamic_cast;
155  RCP<MultiVectorBase<Scalar> > rowStatMultiVec =
156  dyn_cast<MVPV>(*rowStatVec).getNonconstMultiVector().assert_not_null();
157  const Ordinal numCols = rowStatMultiVec->domain()->dim();
158  if (numCols > 0) {
159  rcp_dynamic_cast<const RowStatLinearOpBase<Scalar> >(op_.getConstObj())
160  ->getRowStat(rowStat, rowStatMultiVec->col(0).ptr());
161  for (Ordinal col = 1; col < numCols; ++col) {
162  Thyra::copy(*(rowStatMultiVec->col(0)),
163  rowStatMultiVec->col(col).ptr());
164  }
165  }
166  }
167 
169 
172 
173  virtual bool supportsScaleLeftImpl() const
174  {
175  using Teuchos::rcp_dynamic_cast;
176  return rcp_dynamic_cast<const ScaledLinearOpBase<Scalar> >(
177  op_.getConstObj())
178  ->supportsScaleLeft();
179  }
180 
181  virtual bool supportsScaleRightImpl() const
182  {
183  using Teuchos::rcp_dynamic_cast;
184  return rcp_dynamic_cast<const ScaledLinearOpBase<Scalar> >(
185  op_.getConstObj())
186  ->supportsScaleRight();
187  }
188 
189  virtual void scaleLeftImpl(const VectorBase<Scalar> &row_scaling)
190  {
191  TEUCHOS_ASSERT(this->supportsScaleLeft());
192 
193  // Use the first column in the scaling vector to scale the operator
195  using Teuchos::dyn_cast;
196  using Teuchos::rcp_dynamic_cast;
197  RCP<const MultiVectorBase<Scalar> > row_scaling_mv =
198  dyn_cast<const MVPV>(row_scaling).getMultiVector().assert_not_null();
199  const Ordinal numCols = row_scaling_mv->domain()->dim();
200  if (numCols > 0) {
201  rcp_dynamic_cast<ScaledLinearOpBase<Scalar> >(op_.getNonconstObj())
202  ->scaleLeft(*(row_scaling_mv->col(0)));
203  }
204 
205  // row_scaling.describe(std::cout, Teuchos::VERB_EXTREME);
206  }
207 
208  virtual void scaleRightImpl(const VectorBase<Scalar> &col_scaling)
209  {
210  TEUCHOS_ASSERT(this->supportsScaleRight());
211 
212  // Use the first column in the scaling vector to scale the operator
214  using Teuchos::dyn_cast;
215  using Teuchos::rcp_dynamic_cast;
216  RCP<const MultiVectorBase<Scalar> > col_scaling_mv =
217  dyn_cast<const MVPV>(col_scaling).getMultiVector().assert_not_null();
218  const Ordinal numCols = col_scaling_mv->domain()->dim();
219  if (numCols > 0) {
220  rcp_dynamic_cast<ScaledLinearOpBase<Scalar> >(op_.getNonconstObj())
221  ->scaleRight(*(col_scaling_mv->col(0)));
222  }
223  }
224 
226 
227  private:
228  // //////////////////////////////
229  // Private types
230 
232 
233  // //////////////////////////////
234  // Private data members
235 
237  RCP<const DefaultMultiVectorProductVectorSpace<Scalar> > multiVecRange_;
238  RCP<const DefaultMultiVectorProductVectorSpace<Scalar> > multiVecDomain_;
239 
240  // //////////////////////////////
241  // Private member functions
242 
243  static void validateInitialize(
244  const RCP<const LinearOpBase<Scalar> > &op,
246  &multiVecRange,
248  &multiVecDomain)
249  {
250 #ifdef TEUCHOS_DEBUG
252  TEUCHOS_TEST_FOR_EXCEPT(is_null(multiVecRange));
253  TEUCHOS_TEST_FOR_EXCEPT(is_null(multiVecDomain));
254  TEUCHOS_TEST_FOR_EXCEPT(multiVecRange->numBlocks() !=
255  multiVecDomain->numBlocks());
256  if (op->range() != Teuchos::null)
258  "MultiVectorLinearOp<Scalar>::initialize(op,multiVecRange,"
259  "multiVecDomain)",
260  *op->range(), *multiVecRange->getBlock(0));
261  if (op->domain() != Teuchos::null)
263  "MultiVectorLinearOp<Scalar>::initialize(op,multiVecRange,"
264  "multiVecDomain)",
265  *op->domain(), *multiVecDomain->getBlock(0));
266 #else
267  (void)op;
268  (void)multiVecRange;
269  (void)multiVecDomain;
270 #endif
271  }
272 };
273 
278 template <class Scalar>
279 RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp()
280 {
282 }
283 
288 template <class Scalar>
289 RCP<MultiVectorLinearOp<Scalar> > nonconstMultiVectorLinearOp(
290  const RCP<LinearOpBase<Scalar> > &op,
292  &multiVecRange,
294  &multiVecDomain)
295 {
296  RCP<MultiVectorLinearOp<Scalar> > mvop =
298  mvop->nonconstInitialize(op, multiVecRange, multiVecDomain);
299  return mvop;
300 }
301 
306 template <class Scalar>
307 RCP<MultiVectorLinearOp<Scalar> > nonconstMultiVectorLinearOp(
308  const RCP<LinearOpBase<Scalar> > &op, const int num_blocks)
309 {
310  RCP<MultiVectorLinearOp<Scalar> > mvop =
312  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_domain =
313  Thyra::multiVectorProductVectorSpace(op->domain(), num_blocks);
314  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_range =
315  Thyra::multiVectorProductVectorSpace(op->range(), num_blocks);
316  mvop->nonconstInitialize(op, mv_range, mv_domain);
317  return mvop;
318 }
319 
324 template <class Scalar>
325 RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp(
326  const RCP<const LinearOpBase<Scalar> > &op,
328  &multiVecRange,
330  &multiVecDomain)
331 {
332  RCP<MultiVectorLinearOp<Scalar> > mvop =
334  mvop->initialize(op, multiVecRange, multiVecDomain);
335  return mvop;
336 }
337 
342 template <class Scalar>
343 RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp(
344  const RCP<const LinearOpBase<Scalar> > &op, const int num_blocks)
345 {
346  RCP<MultiVectorLinearOp<Scalar> > mvop =
348  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_domain =
349  Thyra::multiVectorProductVectorSpace(op->domain(), num_blocks);
350  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_range =
351  Thyra::multiVectorProductVectorSpace(op->range(), num_blocks);
352  mvop->initialize(op, mv_range, mv_domain);
353  return mvop;
354 }
355 
356 } // end namespace Thyra
357 
358 #endif
RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > multiVecRange_
#define THYRA_ASSERT_VEC_SPACES(FUNC_NAME, VS1, VS2)
static void validateInitialize(const RCP< const LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
bool is_null(const boost::shared_ptr< T > &p)
EOpTransp
RCP< MultiVectorLinearOp< Scalar > > multiVectorLinearOp()
Nonmember constructor function.
virtual void scaleRightImpl(const VectorBase< Scalar > &col_scaling)
void nonconstInitialize(const RCP< LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
T_To & dyn_cast(T_From &from)
RCP< LinearOpBase< Scalar > > getNonconstLinearOp()
void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat, const Ptr< VectorBase< Scalar > > &rowStatVec) const
Get some statistics about a supported row.
void applyImpl(const EOpTransp M_trans, const MultiVectorBase< Scalar > &XX, const Ptr< MultiVectorBase< Scalar > > &YY, const Scalar alpha, const Scalar beta) const
Teuchos::ConstNonconstObjectContainer< LinearOpBase< Scalar > > CNOP
RCP< const LinearOpBase< Scalar > > clone() const
RCP< MultiVectorLinearOp< Scalar > > multiVectorLinearOp(const RCP< const LinearOpBase< Scalar > > &op, const int num_blocks)
Nonmember constructor function.
MultiVectorLinearOp()
Construct to uninitialized.
RCP< MultiVectorLinearOp< Scalar > > multiVectorLinearOp(const RCP< const LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
Nonmember constructor function.
RCP< MultiVectorLinearOp< Scalar > > nonconstMultiVectorLinearOp(const RCP< LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
Nonmember constructor function.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::Ordinal Ordinal
RCP< const ObjType > getConstObj() const
RCP< const VectorBase< Scalar > > col(Ordinal j) const
RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > multiVecDomain_
RCP< const VectorSpaceBase< Scalar > > range() const
bool opSupportedImpl(EOpTransp M_trans) const
virtual void scaleLeftImpl(const VectorBase< Scalar > &row_scaling)
virtual bool supportsScaleLeftImpl() const
Implicit concrete LinearOpBase subclass that takes a flattended out multi-vector and performs a multi...
virtual RCP< const VectorSpaceBase< Scalar > > domain() const =0
RCP< const VectorSpaceBase< Scalar > > domain() const
RCP< MultiVectorLinearOp< Scalar > > nonconstMultiVectorLinearOp(const RCP< LinearOpBase< Scalar > > &op, const int num_blocks)
Nonmember constructor function.
#define TEUCHOS_ASSERT(assertion_test)
RCP< ObjType > getNonconstObj() const
bool rowStatIsSupportedImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat) const
Determine if a given row stat is supported.
void initialize(const RCP< const LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
virtual bool supportsScaleRightImpl() const
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
RCP< const LinearOpBase< Scalar > > getLinearOp() const