Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_DefaultAddedLinearOp_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_DEFAULT_ADDED_LINEAR_OP_DEF_HPP
11#define THYRA_DEFAULT_ADDED_LINEAR_OP_DEF_HPP
12
13#include "Thyra_DefaultAddedLinearOp_decl.hpp"
14#include "Thyra_DefaultScaledAdjointLinearOp.hpp"
15#include "Thyra_AssertOp.hpp"
16#include "Teuchos_Utils.hpp"
17
18
19namespace Thyra {
20
21
22// Inline members only used in this class impl
23
24
25template<class Scalar>
26inline
27void DefaultAddedLinearOp<Scalar>::assertInitialized() const
28{
29#ifdef TEUCHOS_DEBUG
30 TEUCHOS_TEST_FOR_EXCEPT( !( numOps() > 0 ) );
31#endif
32}
33
34
35template<class Scalar>
36inline
37std::string DefaultAddedLinearOp<Scalar>::getClassName() const
38{
40}
41
42
43template<class Scalar>
44inline
45Ordinal DefaultAddedLinearOp<Scalar>::getRangeDim() const
46{
47 return (numOps() > 0 ? this->range()->dim() : 0);
48}
49
50
51template<class Scalar>
52inline
53Ordinal DefaultAddedLinearOp<Scalar>::getDomainDim() const
54{
55 return (numOps() > 0 ? this->domain()->dim() : 0);
56}
57
58
59// Constructors/initializers/accessors
60
61
62template<class Scalar>
65
66
67template<class Scalar>
69 const ArrayView<const RCP<LinearOpBase<Scalar> > > &Ops )
70{
71 initialize(Ops);
72}
73
74
75template<class Scalar>
77 const ArrayView<const RCP<const LinearOpBase<Scalar> > > &Ops )
78{
79 initialize(Ops);
80}
81
82
83template<class Scalar>
85 const ArrayView<const RCP<LinearOpBase<Scalar> > > &Ops )
86{
87 const int l_numOps = Ops.size();
88 Ops_.resize(l_numOps);
89 for( int k = 0; k < l_numOps; ++k )
90 Ops_[k].initialize(Ops[k]);
91 validateOps();
92 setupDefaultObjectLabel();
93}
94
95
96template<class Scalar>
98 const ArrayView<const RCP<const LinearOpBase<Scalar> > > &Ops )
99{
100 const int l_numOps = Ops.size();
101 Ops_.resize(l_numOps);
102 for( int k = 0; k < l_numOps; ++k )
103 Ops_[k].initialize(Ops[k]);
104 validateOps();
105 setupDefaultObjectLabel();
106}
107
108
109template<class Scalar>
111{
112 Ops_.resize(0);
113 setupDefaultObjectLabel();
114}
115
116
117// Overridden form AddedLinearOpBase
118
119
120template<class Scalar>
122{
123 return Ops_.size();
124}
125
126
127template<class Scalar>
129{
130#ifdef TEUCHOS_DEBUG
131 TEUCHOS_TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
132#endif
133 return Ops_[k].isConst();
134}
135
136
137template<class Scalar>
140{
141#ifdef TEUCHOS_DEBUG
142 TEUCHOS_TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
143#endif
144 return Ops_[k].getNonconstObj();
145}
146
147
148template<class Scalar>
151{
152#ifdef TEUCHOS_DEBUG
153 TEUCHOS_TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
154#endif
155 return Ops_[k];
156}
157
158
159// Overridden from LinearOpBase
160
161
162template<class Scalar>
165{
166 if (numOps()) {
167 return getOp(0)->range();
168 }
169 return Teuchos::null;
170}
171
172
173template<class Scalar>
176{
177 if (numOps()) {
178 return getOp(numOps()-1)->domain();
179 }
180 return Teuchos::null;
181}
182
183
184template<class Scalar>
187{
188 return Teuchos::null; // Not supported yet but could be!
189}
190
191
192// Overridden from Teuchos::Describable
193
194
195template<class Scalar>
197{
198 std::ostringstream oss;
199 oss << getClassName() << "{numOps="<<numOps()
200 <<",rangeDim=" << getRangeDim()
201 << ",domainDim="<< getDomainDim() <<"}";
202 return oss.str();
203}
204
205
206template<class Scalar>
208 Teuchos::FancyOStream &out_arg
209 ,const Teuchos::EVerbosityLevel verbLevel
210 ) const
211{
212 using Teuchos::RCP;
214 using Teuchos::OSTab;
215 RCP<FancyOStream> out = rcp(&out_arg,false);
216 OSTab tab(out);
217 const int l_numOps = Ops_.size();
218 switch(verbLevel) {
221 *out << this->description() << std::endl;
222 break;
226 {
227 *out << this->description() << std::endl;
228 OSTab tab2(out);
229 *out
230 << "Constituent LinearOpBase objects for M = Op[0]*...*Op[numOps-1]:\n";
231 tab.incrTab();
232 for( int k = 0; k < l_numOps; ++k ) {
233 *out << "Op["<<k<<"] = " << Teuchos::describe(*getOp(k),verbLevel);
234 }
235 break;
236 }
237 default:
238 TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
239 }
240}
241
242
243// protected
244
245
246// Overridden from LinearOpBase
247
248
249template<class Scalar>
251{
252 bool isOpSupported = true;
253 for( int k = 0; k < static_cast<int>(Ops_.size()); ++k )
254 if(!Thyra::opSupported(*getOp(k),M_trans)) isOpSupported = false;
255 return isOpSupported;
256 // ToDo: Cache these?
257}
258
259
260template<class Scalar>
262 const EOpTransp M_trans,
264 const Ptr<MultiVectorBase<Scalar> > &Y,
265 const Scalar alpha,
266 const Scalar beta
267 ) const
268{
270#ifdef TEUCHOS_DEBUG
272 getClassName()+"::apply(...)", *this, M_trans, X, &*Y
273 );
274#endif // TEUCHOS_DEBUG
275 //
276 // Y = alpha * op(M) * X + beta*Y
277 //
278 // =>
279 //
280 // Y = beta*Y + sum(alpha*op(Op[j])*X),j=0...numOps-1)
281 //
282 const int l_numOps = Ops_.size();
283 for( int j = 0; j < l_numOps; ++j )
284 Thyra::apply(*getOp(j), M_trans, X, Y, alpha, j==0 ? beta : ST::one());
285}
286
287
288// private
289
290
291template<class Scalar>
293{
294 using Teuchos::toString;
295#ifdef TEUCHOS_DEBUG
296 try {
297 const int l_numOps = Ops_.size();
298 for( int k = 0; k < l_numOps; ++k ) {
299 TEUCHOS_TEST_FOR_EXCEPT( Ops_[k]().get() == NULL );
300 if( k > 0 ) {
302 getClassName()+"::initialize(...)"
303 ,*Ops_[0], NOTRANS, ("Ops[0]")
304 ,*Ops_[k], NOTRANS, ("Ops["+toString(k)+"]")
305 );
306 }
307 }
308 }
309 catch(...) {
310 uninitialize();
311 throw;
312 }
313#endif
314}
315
316
317template<class Scalar>
318void DefaultAddedLinearOp<Scalar>::setupDefaultObjectLabel()
319{
320 std::ostringstream label;
321 const int l_numOps = Ops_.size();
322 for( int k = 0; k < l_numOps; ++k ) {
323 std::string Op_k_label = Ops_[k]->getObjectLabel();
324 if (Op_k_label.length() == 0)
325 Op_k_label = "ANYM";
326 if (k > 0)
327 label << "+";
328 label << "("<<Op_k_label<<")";
329 }
330 this->setObjectLabel(label.str());
331 validateOps();
332}
333
334
335} // end namespace Thyra
336
337
338template<class Scalar>
340Thyra::nonconstAdd(
341 const RCP<LinearOpBase<Scalar> > &A,
342 const RCP<LinearOpBase<Scalar> > &B,
343 const std::string &label
344 )
345{
346 using Teuchos::tuple;
347 RCP<LinearOpBase<Scalar> > alo =
348 defaultAddedLinearOp<Scalar>(
349 tuple<RCP<LinearOpBase<Scalar> > >(A, B)()
350 );
351 if (label.length())
352 alo->setObjectLabel(label);
353 return alo;
354}
355
356
357template<class Scalar>
359Thyra::add(
360 const RCP<const LinearOpBase<Scalar> > &A,
361 const RCP<const LinearOpBase<Scalar> > &B,
362 const std::string &label
363 )
364{
365 using Teuchos::tuple;
366 RCP<LinearOpBase<Scalar> > alo =
367 defaultAddedLinearOp<Scalar>(
368 tuple<RCP<const LinearOpBase<Scalar> > >(A, B)()
369 );
370 if (label.length())
371 alo->setObjectLabel(label);
372 return alo;
373}
374
375
376template<class Scalar>
378Thyra::nonconstSubtract(
379 const RCP<LinearOpBase<Scalar> > &A,
380 const RCP<LinearOpBase<Scalar> > &B,
381 const std::string &label
382 )
383{
384 typedef ScalarTraits<Scalar> ST;
385 using Teuchos::tuple;
386 RCP<LinearOpBase<Scalar> > alo =
387 defaultAddedLinearOp<Scalar>(
388 tuple<RCP<LinearOpBase<Scalar> > >(
389 A, nonconstScale<Scalar>(-ST::one(),B) )()
390 );
391 if (label.length())
392 alo->setObjectLabel(label);
393 return alo;
394}
395
396
397template<class Scalar>
399Thyra::subtract(
400 const RCP<const LinearOpBase<Scalar> > &A,
401 const RCP<const LinearOpBase<Scalar> > &B,
402 const std::string &label
403 )
404{
405 typedef ScalarTraits<Scalar> ST;
406 using Teuchos::tuple;
407 RCP<LinearOpBase<Scalar> > alo =
408 defaultAddedLinearOp<Scalar>(
409 tuple<RCP<const LinearOpBase<Scalar> > >(
410 A, scale<Scalar>(-ST::one(),B)
411 )()
412 );
413 if (label.length())
414 alo->setObjectLabel(label);
415 return alo;
416}
417
418
419//
420// Explicit instantiation macro
421//
422
423#define THYRA_DEFAULT_ADDED_LINEAR_OP_INSTANT(SCALAR) \
424 template class DefaultAddedLinearOp<SCALAR >; \
425 \
426 template RCP<LinearOpBase<SCALAR > > \
427 nonconstAdd( \
428 const RCP<LinearOpBase<SCALAR > > &A, \
429 const RCP<LinearOpBase<SCALAR > > &B, \
430 const std::string &label \
431 ); \
432 \
433 template RCP<const LinearOpBase<SCALAR > > \
434 add( \
435 const RCP<const LinearOpBase<SCALAR > > &A, \
436 const RCP<const LinearOpBase<SCALAR > > &B, \
437 const std::string &label \
438 ); \
439 \
440 template RCP<LinearOpBase<SCALAR > > \
441 nonconstSubtract( \
442 const RCP<LinearOpBase<SCALAR > > &A, \
443 const RCP<LinearOpBase<SCALAR > > &B, \
444 const std::string &label \
445 ); \
446 \
447 template RCP<const LinearOpBase<SCALAR > > \
448 subtract( \
449 const RCP<const LinearOpBase<SCALAR > > &A, \
450 const RCP<const LinearOpBase<SCALAR > > &B, \
451 const std::string &label \
452 );
453
454
455#endif // THYRA_DEFAULT_ADDED_LINEAR_OP_DEF_HPP
virtual std::string description() const
Concrete composite LinearOpBase subclass that creates an implicitly added linear operator out of one ...
RCP< LinearOpBase< Scalar > > getNonconstOp(const int k)
void applyImpl(const EOpTransp M_trans, const MultiVectorBase< Scalar > &X, const Ptr< MultiVectorBase< Scalar > > &Y, const Scalar alpha, const Scalar beta) const
std::string description() const
Prints just the name DefaultAddedLinearOp along with the overall dimensions and the number of constit...
RCP< const VectorSpaceBase< Scalar > > domain() const
Returns this->getOp(this->numOps()-1).domain() if <t>this->numOps() > 0 and returns Teuchos::null oth...
RCP< const VectorSpaceBase< Scalar > > range() const
Returns this->getOp(0).range() if <t>this->numOps() > 0 and returns Teuchos::null otherwise.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Prints the details about the constituent linear operators.
DefaultAddedLinearOp()
Constructs to uninitialized.
void initialize(const ArrayView< const RCP< LinearOpBase< Scalar > > > &Ops)
Initialize given a list of non-const linear operators.
bool opSupportedImpl(EOpTransp M_trans) const
Returns true only if all constituent operators support M_trans.
RCP< const LinearOpBase< Scalar > > clone() const
RCP< const LinearOpBase< Scalar > > getOp(const int k) const
Base class for all linear operators.
Interface for a collection of column vectors called a multi-vector.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define THYRA_ASSERT_LINEAR_OP_MULTIVEC_APPLY_SPACES(FUNC_NAME, M, M_T, X, Y)
This is a very useful macro that should be used to validate that the spaces for the multi-vector vers...
#define THYRA_ASSERT_LINEAR_OP_PLUS_LINEAR_OP_SPACES_NAMES(FUNC_NAME, M1, M1_T, M1_N, M2, M2_T, M2_N)
Assert that a linear operator addition matches up.
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
const char * toString(EConj conj)
Return a string name for a EOpTransp value. `*.
@ NOTRANS
Use the non-transposed operator.
T_To & dyn_cast(T_From &from)
std::string toString(const T &t)