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: Time Integration and Sensitivity Analysis Package
4 //
5 // Copyright 2017 NTESS and the Tempus contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 //@HEADER
9 
10 #ifndef Thyra_MultiVectorLinearOp_hpp
11 #define Thyra_MultiVectorLinearOp_hpp
12 
13 #include "Thyra_RowStatLinearOpBase.hpp"
14 #include "Thyra_ScaledLinearOpBase.hpp"
15 #include "Thyra_DefaultMultiVectorProductVectorSpace.hpp"
16 #include "Thyra_DefaultMultiVectorProductVector.hpp"
17 #include "Teuchos_ConstNonconstObjectContainer.hpp"
18 #include "Thyra_VectorStdOps.hpp"
19 #include "Thyra_MultiVectorStdOps.hpp"
20 #include "Thyra_AssertOp.hpp"
21 #include "Teuchos_dyn_cast.hpp"
22 
23 namespace Thyra {
24 
29 template <class Scalar>
30 class MultiVectorLinearOp : virtual public RowStatLinearOpBase<Scalar>,
31  virtual public ScaledLinearOpBase<Scalar> {
32  public:
35 
38 
40  const RCP<LinearOpBase<Scalar> > &op,
42  &multiVecRange,
44  &multiVecDomain)
45  {
46  validateInitialize(op, multiVecRange, multiVecDomain);
47  op_ = op;
48  multiVecRange_ = multiVecRange;
49  multiVecDomain_ = multiVecDomain;
50  }
51 
52  void initialize(const RCP<const LinearOpBase<Scalar> > &op,
54  &multiVecRange,
56  &multiVecDomain)
57  {
58  validateInitialize(op, multiVecRange, multiVecDomain);
59  op_ = op;
60  multiVecRange_ = multiVecRange;
61  multiVecDomain_ = multiVecDomain;
62  }
63 
64  RCP<LinearOpBase<Scalar> > getNonconstLinearOp()
65  {
66  return op_.getNonconstObj();
67  }
68 
69  RCP<const LinearOpBase<Scalar> > getLinearOp() const
70  {
71  return op_.getConstObj();
72  }
73 
74  void uninitialize()
75  {
76  op_.uninitialize();
77  multiVecRange_ = Teuchos::null;
78  multiVecDomain_ = Teuchos::null;
79  }
80 
82 
85 
86  RCP<const VectorSpaceBase<Scalar> > range() const { return multiVecRange_; }
87 
88  RCP<const VectorSpaceBase<Scalar> > domain() const { return multiVecDomain_; }
89 
90  RCP<const LinearOpBase<Scalar> > clone() const
91  {
92  return Teuchos::null; // ToDo: Implement if needed ???
93  }
95 
96  protected:
99  bool opSupportedImpl(EOpTransp M_trans) const
100  {
101  return Thyra::opSupported(*op_.getConstObj(), M_trans);
102  }
103 
104  void applyImpl(const EOpTransp M_trans, const MultiVectorBase<Scalar> &XX,
105  const Ptr<MultiVectorBase<Scalar> > &YY, const Scalar alpha,
106  const Scalar beta) const
107  {
108  using Teuchos::dyn_cast;
110 
111  const Ordinal numCols = XX.domain()->dim();
112 
113  for (Ordinal col_j = 0; col_j < numCols; ++col_j) {
114  const RCP<const VectorBase<Scalar> > x = XX.col(col_j);
115  const RCP<VectorBase<Scalar> > y = YY->col(col_j);
116 
117  RCP<const MultiVectorBase<Scalar> > X =
118  dyn_cast<const MVPV>(*x).getMultiVector().assert_not_null();
119  RCP<MultiVectorBase<Scalar> > Y =
120  dyn_cast<MVPV>(*y).getNonconstMultiVector().assert_not_null();
121 
122  Thyra::apply(*op_.getConstObj(), M_trans, *X, Y.ptr(), alpha, beta);
123  }
124  }
126 
129 
132  const RowStatLinearOpBaseUtils::ERowStat rowStat) const
133  {
134  using Teuchos::rcp_dynamic_cast;
135  return rcp_dynamic_cast<const RowStatLinearOpBase<Scalar> >(
136  op_.getConstObj())
137  ->rowStatIsSupported(rowStat);
138  }
139 
144  void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat,
145  const Ptr<VectorBase<Scalar> > &rowStatVec) const
146  {
147  TEUCHOS_ASSERT(this->rowStatIsSupported(rowStat));
148 
149  // Compute the scaling vector from the underlying operator and assign
150  // it to each column of the scaling multivector. We only use the first
151  // column in the scaling below, but this makes the scaling vector
152  // consistent with a Kronecker-product operator
154  using Teuchos::dyn_cast;
155  using Teuchos::rcp_dynamic_cast;
156  RCP<MultiVectorBase<Scalar> > rowStatMultiVec =
157  dyn_cast<MVPV>(*rowStatVec).getNonconstMultiVector().assert_not_null();
158  const Ordinal numCols = rowStatMultiVec->domain()->dim();
159  if (numCols > 0) {
160  rcp_dynamic_cast<const RowStatLinearOpBase<Scalar> >(op_.getConstObj())
161  ->getRowStat(rowStat, rowStatMultiVec->col(0).ptr());
162  for (Ordinal col = 1; col < numCols; ++col) {
163  Thyra::copy(*(rowStatMultiVec->col(0)),
164  rowStatMultiVec->col(col).ptr());
165  }
166  }
167  }
168 
170 
173 
174  virtual bool supportsScaleLeftImpl() const
175  {
176  using Teuchos::rcp_dynamic_cast;
177  return rcp_dynamic_cast<const ScaledLinearOpBase<Scalar> >(
178  op_.getConstObj())
179  ->supportsScaleLeft();
180  }
181 
182  virtual bool supportsScaleRightImpl() const
183  {
184  using Teuchos::rcp_dynamic_cast;
185  return rcp_dynamic_cast<const ScaledLinearOpBase<Scalar> >(
186  op_.getConstObj())
187  ->supportsScaleRight();
188  }
189 
190  virtual void scaleLeftImpl(const VectorBase<Scalar> &row_scaling)
191  {
192  TEUCHOS_ASSERT(this->supportsScaleLeft());
193 
194  // Use the first column in the scaling vector to scale the operator
196  using Teuchos::dyn_cast;
197  using Teuchos::rcp_dynamic_cast;
198  RCP<const MultiVectorBase<Scalar> > row_scaling_mv =
199  dyn_cast<const MVPV>(row_scaling).getMultiVector().assert_not_null();
200  const Ordinal numCols = row_scaling_mv->domain()->dim();
201  if (numCols > 0) {
202  rcp_dynamic_cast<ScaledLinearOpBase<Scalar> >(op_.getNonconstObj())
203  ->scaleLeft(*(row_scaling_mv->col(0)));
204  }
205 
206  // row_scaling.describe(std::cout, Teuchos::VERB_EXTREME);
207  }
208 
209  virtual void scaleRightImpl(const VectorBase<Scalar> &col_scaling)
210  {
211  TEUCHOS_ASSERT(this->supportsScaleRight());
212 
213  // Use the first column in the scaling vector to scale the operator
215  using Teuchos::dyn_cast;
216  using Teuchos::rcp_dynamic_cast;
217  RCP<const MultiVectorBase<Scalar> > col_scaling_mv =
218  dyn_cast<const MVPV>(col_scaling).getMultiVector().assert_not_null();
219  const Ordinal numCols = col_scaling_mv->domain()->dim();
220  if (numCols > 0) {
221  rcp_dynamic_cast<ScaledLinearOpBase<Scalar> >(op_.getNonconstObj())
222  ->scaleRight(*(col_scaling_mv->col(0)));
223  }
224  }
225 
227 
228  private:
229  // //////////////////////////////
230  // Private types
231 
233 
234  // //////////////////////////////
235  // Private data members
236 
238  RCP<const DefaultMultiVectorProductVectorSpace<Scalar> > multiVecRange_;
239  RCP<const DefaultMultiVectorProductVectorSpace<Scalar> > multiVecDomain_;
240 
241  // //////////////////////////////
242  // Private member functions
243 
244  static void validateInitialize(
245  const RCP<const LinearOpBase<Scalar> > &op,
247  &multiVecRange,
249  &multiVecDomain)
250  {
251 #ifdef TEUCHOS_DEBUG
253  TEUCHOS_TEST_FOR_EXCEPT(is_null(multiVecRange));
254  TEUCHOS_TEST_FOR_EXCEPT(is_null(multiVecDomain));
255  TEUCHOS_TEST_FOR_EXCEPT(multiVecRange->numBlocks() !=
256  multiVecDomain->numBlocks());
257  if (op->range() != Teuchos::null)
259  "MultiVectorLinearOp<Scalar>::initialize(op,multiVecRange,"
260  "multiVecDomain)",
261  *op->range(), *multiVecRange->getBlock(0));
262  if (op->domain() != Teuchos::null)
264  "MultiVectorLinearOp<Scalar>::initialize(op,multiVecRange,"
265  "multiVecDomain)",
266  *op->domain(), *multiVecDomain->getBlock(0));
267 #else
268  (void)op;
269  (void)multiVecRange;
270  (void)multiVecDomain;
271 #endif
272  }
273 };
274 
279 template <class Scalar>
280 RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp()
281 {
283 }
284 
289 template <class Scalar>
290 RCP<MultiVectorLinearOp<Scalar> > nonconstMultiVectorLinearOp(
291  const RCP<LinearOpBase<Scalar> > &op,
293  &multiVecRange,
295  &multiVecDomain)
296 {
297  RCP<MultiVectorLinearOp<Scalar> > mvop =
299  mvop->nonconstInitialize(op, multiVecRange, multiVecDomain);
300  return mvop;
301 }
302 
307 template <class Scalar>
308 RCP<MultiVectorLinearOp<Scalar> > nonconstMultiVectorLinearOp(
309  const RCP<LinearOpBase<Scalar> > &op, const int num_blocks)
310 {
311  RCP<MultiVectorLinearOp<Scalar> > mvop =
313  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_domain =
314  Thyra::multiVectorProductVectorSpace(op->domain(), num_blocks);
315  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_range =
316  Thyra::multiVectorProductVectorSpace(op->range(), num_blocks);
317  mvop->nonconstInitialize(op, mv_range, mv_domain);
318  return mvop;
319 }
320 
325 template <class Scalar>
326 RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp(
327  const RCP<const LinearOpBase<Scalar> > &op,
329  &multiVecRange,
331  &multiVecDomain)
332 {
333  RCP<MultiVectorLinearOp<Scalar> > mvop =
335  mvop->initialize(op, multiVecRange, multiVecDomain);
336  return mvop;
337 }
338 
343 template <class Scalar>
344 RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp(
345  const RCP<const LinearOpBase<Scalar> > &op, const int num_blocks)
346 {
347  RCP<MultiVectorLinearOp<Scalar> > mvop =
349  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_domain =
350  Thyra::multiVectorProductVectorSpace(op->domain(), num_blocks);
351  RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_range =
352  Thyra::multiVectorProductVectorSpace(op->range(), num_blocks);
353  mvop->initialize(op, mv_range, mv_domain);
354  return mvop;
355 }
356 
357 } // end namespace Thyra
358 
359 #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