Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
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
23namespace Thyra {
24
29template <class Scalar>
30class MultiVectorLinearOp : virtual public RowStatLinearOpBase<Scalar>,
31 virtual public ScaledLinearOpBase<Scalar> {
32 public:
35
38
40 const RCP<LinearOpBase<Scalar> > &op,
41 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
42 &multiVecRange,
43 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
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,
53 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
54 &multiVecRange,
55 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
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
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 }
94
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;
109 typedef DefaultMultiVectorProductVector<Scalar> MVPV;
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 }
125
126
129
133 const RowStatLinearOpBaseUtils::ERowStat rowStat) const
134 {
135 using Teuchos::rcp_dynamic_cast;
136 RCP<const RowStatLinearOpBase<Scalar> > row_stat_op =
137 rcp_dynamic_cast<const RowStatLinearOpBase<Scalar> >(
138 op_.getConstObj());
139 return nonnull(row_stat_op) && row_stat_op->rowStatIsSupported(rowStat);
140 }
141
146 void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat,
147 const Ptr<VectorBase<Scalar> > &rowStatVec) const
148 {
149 TEUCHOS_ASSERT(this->rowStatIsSupported(rowStat));
150
151 // Compute the scaling vector from the underlying operator and assign
152 // it to each column of the scaling multivector. We only use the first
153 // column in the scaling below, but this makes the scaling vector
154 // consistent with a Kronecker-product operator
155 typedef DefaultMultiVectorProductVector<Scalar> MVPV;
156 using Teuchos::dyn_cast;
157 using Teuchos::rcp_dynamic_cast;
158 RCP<MultiVectorBase<Scalar> > rowStatMultiVec =
159 dyn_cast<MVPV>(*rowStatVec).getNonconstMultiVector().assert_not_null();
160 const Ordinal numCols = rowStatMultiVec->domain()->dim();
161 if (numCols > 0) {
162 rcp_dynamic_cast<const RowStatLinearOpBase<Scalar> >(op_.getConstObj())
163 ->getRowStat(rowStat, rowStatMultiVec->col(0).ptr());
164 for (Ordinal col = 1; col < numCols; ++col) {
165 Thyra::copy(*(rowStatMultiVec->col(0)),
166 rowStatMultiVec->col(col).ptr());
167 }
168 }
169 }
170
172
175
177 virtual bool supportsScaleLeftImpl() const
178 {
179 using Teuchos::rcp_dynamic_cast;
180 RCP<const ScaledLinearOpBase<Scalar> > scaled_op =
181 rcp_dynamic_cast<const ScaledLinearOpBase<Scalar> >(
182 op_.getConstObj());
183 return nonnull(scaled_op) && scaled_op->supportsScaleLeft();
184 }
185
187 virtual bool supportsScaleRightImpl() const
188 {
189 using Teuchos::rcp_dynamic_cast;
190 RCP<const ScaledLinearOpBase<Scalar> > scaled_op =
191 rcp_dynamic_cast<const ScaledLinearOpBase<Scalar> >(
192 op_.getConstObj());
193 return nonnull(scaled_op) && scaled_op->supportsScaleRight();
194 }
195
196 virtual void scaleLeftImpl(const VectorBase<Scalar> &row_scaling)
197 {
198 TEUCHOS_ASSERT(this->supportsScaleLeft());
199
200 // Use the first column in the scaling vector to scale the operator
201 typedef DefaultMultiVectorProductVector<Scalar> MVPV;
202 using Teuchos::dyn_cast;
203 using Teuchos::rcp_dynamic_cast;
204 RCP<const MultiVectorBase<Scalar> > row_scaling_mv =
205 dyn_cast<const MVPV>(row_scaling).getMultiVector().assert_not_null();
206 const Ordinal numCols = row_scaling_mv->domain()->dim();
207 if (numCols > 0) {
208 rcp_dynamic_cast<ScaledLinearOpBase<Scalar> >(op_.getNonconstObj())
209 ->scaleLeft(*(row_scaling_mv->col(0)));
210 }
211
212 // row_scaling.describe(std::cout, Teuchos::VERB_EXTREME);
213 }
214
215 virtual void scaleRightImpl(const VectorBase<Scalar> &col_scaling)
216 {
217 TEUCHOS_ASSERT(this->supportsScaleRight());
218
219 // Use the first column in the scaling vector to scale the operator
220 typedef DefaultMultiVectorProductVector<Scalar> MVPV;
221 using Teuchos::dyn_cast;
222 using Teuchos::rcp_dynamic_cast;
223 RCP<const MultiVectorBase<Scalar> > col_scaling_mv =
224 dyn_cast<const MVPV>(col_scaling).getMultiVector().assert_not_null();
225 const Ordinal numCols = col_scaling_mv->domain()->dim();
226 if (numCols > 0) {
227 rcp_dynamic_cast<ScaledLinearOpBase<Scalar> >(op_.getNonconstObj())
228 ->scaleRight(*(col_scaling_mv->col(0)));
229 }
230 }
231
233
234 private:
235 // //////////////////////////////
236 // Private types
237
238 typedef Teuchos::ConstNonconstObjectContainer<LinearOpBase<Scalar> > CNOP;
239
240 // //////////////////////////////
241 // Private data members
242
244 RCP<const DefaultMultiVectorProductVectorSpace<Scalar> > multiVecRange_;
245 RCP<const DefaultMultiVectorProductVectorSpace<Scalar> > multiVecDomain_;
246
247 // //////////////////////////////
248 // Private member functions
249
251 const RCP<const LinearOpBase<Scalar> > &op,
252 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
253 &multiVecRange,
254 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
255 &multiVecDomain)
256 {
257#ifdef TEUCHOS_DEBUG
258 TEUCHOS_TEST_FOR_EXCEPT(is_null(op));
259 TEUCHOS_TEST_FOR_EXCEPT(is_null(multiVecRange));
260 TEUCHOS_TEST_FOR_EXCEPT(is_null(multiVecDomain));
261 TEUCHOS_TEST_FOR_EXCEPT(multiVecRange->numBlocks() !=
262 multiVecDomain->numBlocks());
263 if (op->range() != Teuchos::null)
264 THYRA_ASSERT_VEC_SPACES(
265 "MultiVectorLinearOp<Scalar>::initialize(op,multiVecRange,"
266 "multiVecDomain)",
267 *op->range(), *multiVecRange->getBlock(0));
268 if (op->domain() != Teuchos::null)
269 THYRA_ASSERT_VEC_SPACES(
270 "MultiVectorLinearOp<Scalar>::initialize(op,multiVecRange,"
271 "multiVecDomain)",
272 *op->domain(), *multiVecDomain->getBlock(0));
273#else
274 (void)op;
275 (void)multiVecRange;
276 (void)multiVecDomain;
277#endif
278 }
279};
280
285template <class Scalar>
286RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp()
287{
288 return Teuchos::rcp(new MultiVectorLinearOp<Scalar>());
289}
290
295template <class Scalar>
296RCP<MultiVectorLinearOp<Scalar> > nonconstMultiVectorLinearOp(
297 const RCP<LinearOpBase<Scalar> > &op,
298 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
299 &multiVecRange,
300 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
301 &multiVecDomain)
302{
303 RCP<MultiVectorLinearOp<Scalar> > mvop =
304 Teuchos::rcp(new MultiVectorLinearOp<Scalar>());
305 mvop->nonconstInitialize(op, multiVecRange, multiVecDomain);
306 return mvop;
307}
308
313template <class Scalar>
314RCP<MultiVectorLinearOp<Scalar> > nonconstMultiVectorLinearOp(
315 const RCP<LinearOpBase<Scalar> > &op, const int num_blocks)
316{
317 RCP<MultiVectorLinearOp<Scalar> > mvop =
318 Teuchos::rcp(new MultiVectorLinearOp<Scalar>());
319 RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_domain =
320 Thyra::multiVectorProductVectorSpace(op->domain(), num_blocks);
321 RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_range =
322 Thyra::multiVectorProductVectorSpace(op->range(), num_blocks);
323 mvop->nonconstInitialize(op, mv_range, mv_domain);
324 return mvop;
325}
326
331template <class Scalar>
332RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp(
333 const RCP<const LinearOpBase<Scalar> > &op,
334 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
335 &multiVecRange,
336 const RCP<const DefaultMultiVectorProductVectorSpace<Scalar> >
337 &multiVecDomain)
338{
339 RCP<MultiVectorLinearOp<Scalar> > mvop =
340 Teuchos::rcp(new MultiVectorLinearOp<Scalar>());
341 mvop->initialize(op, multiVecRange, multiVecDomain);
342 return mvop;
343}
344
349template <class Scalar>
350RCP<MultiVectorLinearOp<Scalar> > multiVectorLinearOp(
351 const RCP<const LinearOpBase<Scalar> > &op, const int num_blocks)
352{
353 RCP<MultiVectorLinearOp<Scalar> > mvop =
354 Teuchos::rcp(new MultiVectorLinearOp<Scalar>());
355 RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_domain =
356 Thyra::multiVectorProductVectorSpace(op->domain(), num_blocks);
357 RCP<const Thyra::DefaultMultiVectorProductVectorSpace<Scalar> > mv_range =
358 Thyra::multiVectorProductVectorSpace(op->range(), num_blocks);
359 mvop->initialize(op, mv_range, mv_domain);
360 return mvop;
361}
362
363} // end namespace Thyra
364
365#endif
RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > multiVecDomain_
virtual void scaleRightImpl(const VectorBase< Scalar > &col_scaling)
void initialize(const RCP< const LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
MultiVectorLinearOp()
Construct to uninitialized.
void applyImpl(const EOpTransp M_trans, const MultiVectorBase< Scalar > &XX, const Ptr< MultiVectorBase< Scalar > > &YY, const Scalar alpha, const Scalar beta) const
bool rowStatIsSupportedImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat) const
Determine if a given row stat is supported (false if the underlying operator is not a RowStatLinearOp...
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.
void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat, const Ptr< VectorBase< Scalar > > &rowStatVec) const
Get some statistics about a supported row.
static void validateInitialize(const RCP< const LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
bool opSupportedImpl(EOpTransp M_trans) const
RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > multiVecRange_
RCP< MultiVectorLinearOp< Scalar > > multiVectorLinearOp()
Nonmember constructor function.
RCP< LinearOpBase< Scalar > > getNonconstLinearOp()
RCP< const LinearOpBase< Scalar > > getLinearOp() const
Teuchos::ConstNonconstObjectContainer< LinearOpBase< Scalar > > CNOP
RCP< const VectorSpaceBase< Scalar > > domain() const
RCP< MultiVectorLinearOp< Scalar > > nonconstMultiVectorLinearOp(const RCP< LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
Nonmember constructor function.
virtual bool supportsScaleLeftImpl() const
False if the underlying operator is not a ScaledLinearOpBase.
void nonconstInitialize(const RCP< LinearOpBase< Scalar > > &op, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecRange, const RCP< const DefaultMultiVectorProductVectorSpace< Scalar > > &multiVecDomain)
RCP< MultiVectorLinearOp< Scalar > > nonconstMultiVectorLinearOp(const RCP< LinearOpBase< Scalar > > &op, const int num_blocks)
Nonmember constructor function.
virtual void scaleLeftImpl(const VectorBase< Scalar > &row_scaling)
RCP< const VectorSpaceBase< Scalar > > range() const
RCP< const LinearOpBase< Scalar > > clone() const
virtual bool supportsScaleRightImpl() const
False if the underlying operator is not a ScaledLinearOpBase.
RCP< MultiVectorLinearOp< Scalar > > multiVectorLinearOp(const RCP< const LinearOpBase< Scalar > > &op, const int num_blocks)
Nonmember constructor function.