Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
19 namespace Thyra {
20 
21 
22 // Inline members only used in this class impl
23 
24 
25 template<class Scalar>
26 inline
27 void DefaultAddedLinearOp<Scalar>::assertInitialized() const
28 {
29 #ifdef TEUCHOS_DEBUG
30  TEUCHOS_TEST_FOR_EXCEPT( !( numOps() > 0 ) );
31 #endif
32 }
33 
34 
35 template<class Scalar>
36 inline
37 std::string DefaultAddedLinearOp<Scalar>::getClassName() const
38 {
40 }
41 
42 
43 template<class Scalar>
44 inline
45 Ordinal DefaultAddedLinearOp<Scalar>::getRangeDim() const
46 {
47  return (numOps() > 0 ? this->range()->dim() : 0);
48 }
49 
50 
51 template<class Scalar>
52 inline
53 Ordinal DefaultAddedLinearOp<Scalar>::getDomainDim() const
54 {
55  return (numOps() > 0 ? this->domain()->dim() : 0);
56 }
57 
58 
59 // Constructors/initializers/accessors
60 
61 
62 template<class Scalar>
64 {}
65 
66 
67 template<class Scalar>
69  const ArrayView<const RCP<LinearOpBase<Scalar> > > &Ops )
70 {
71  initialize(Ops);
72 }
73 
74 
75 template<class Scalar>
77  const ArrayView<const RCP<const LinearOpBase<Scalar> > > &Ops )
78 {
79  initialize(Ops);
80 }
81 
82 
83 template<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 
96 template<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 
109 template<class Scalar>
111 {
112  Ops_.resize(0);
113  setupDefaultObjectLabel();
114 }
115 
116 
117 // Overridden form AddedLinearOpBase
118 
119 
120 template<class Scalar>
122 {
123  return Ops_.size();
124 }
125 
126 
127 template<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 
137 template<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 
148 template<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 
162 template<class Scalar>
165 {
166  if (numOps()) {
167  return getOp(0)->range();
168  }
169  return Teuchos::null;
170 }
171 
172 
173 template<class Scalar>
176 {
177  if (numOps()) {
178  return getOp(numOps()-1)->domain();
179  }
180  return Teuchos::null;
181 }
182 
183 
184 template<class Scalar>
187 {
188  return Teuchos::null; // Not supported yet but could be!
189 }
190 
191 
192 // Overridden from Teuchos::Describable
193 
194 
195 template<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 
206 template<class Scalar>
208  Teuchos::FancyOStream &out_arg
209  ,const Teuchos::EVerbosityLevel verbLevel
210  ) const
211 {
212  using Teuchos::RCP;
213  using Teuchos::FancyOStream;
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) {
220  case Teuchos::VERB_LOW:
221  *out << this->description() << std::endl;
222  break;
224  case Teuchos::VERB_HIGH:
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 
249 template<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 
260 template<class Scalar>
262  const EOpTransp M_trans,
263  const MultiVectorBase<Scalar> &X,
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 
291 template<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 
317 template<class Scalar>
318 void 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 
338 template<class Scalar>
340 Thyra::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 
357 template<class Scalar>
359 Thyra::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 
376 template<class Scalar>
378 Thyra::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 
397 template<class Scalar>
399 Thyra::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
bool opSupportedImpl(EOpTransp M_trans) const
Returns true only if all constituent operators support M_trans.
void initialize(int *argc, char ***argv)
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
basic_OSTab< char > OSTab
#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.
basic_FancyOStream< char > FancyOStream
Use the non-transposed operator.
RCP< const VectorSpaceBase< Scalar > > range() const
Returns this-&gt;getOp(0).range() if &lt;t&gt;this-&gt;numOps() &gt; 0 and returns Teuchos::null otherwise...
RCP< const LinearOpBase< Scalar > > clone() const
Concrete composite LinearOpBase subclass that creates an implicitly added linear operator out of one ...
DefaultAddedLinearOp()
Constructs to uninitialized.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::Ordinal Ordinal
Type for the dimension of a vector space. `*.
Interface for a collection of column vectors called a multi-vector.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Prints the details about the constituent linear operators.
void initialize(const ArrayView< const RCP< LinearOpBase< Scalar > > > &Ops)
Initialize given a list of non-const linear operators.
virtual std::string description() const
RCP< LinearOpBase< Scalar > > getNonconstOp(const int k)
TEUCHOSCORE_LIB_DLL_EXPORT std::string toString(const EVerbosityLevel verbLevel)
void uninitialize()
Set to uninitialized.
Base class for all linear operators.
std::string description() const
Prints just the name DefaultAddedLinearOp along with the overall dimensions and the number of constit...
void applyImpl(const EOpTransp M_trans, const MultiVectorBase< Scalar > &X, const Ptr< MultiVectorBase< Scalar > > &Y, const Scalar alpha, const Scalar beta) const
RCP< const VectorSpaceBase< Scalar > > domain() const
Returns this-&gt;getOp(this-&gt;numOps()-1).domain() if &lt;t&gt;this-&gt;numOps() &gt; 0 and returns Teuchos::null oth...
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
std::string toString(const T &t)
RCP< const LinearOpBase< Scalar > > getOp(const int k) const