Thyra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_DefaultMultipliedLinearOp_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_MULTIPLIED_LINEAR_OP_DEF_HPP
11 #define THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_DEF_HPP
12 
13 #include "Thyra_DefaultMultipliedLinearOp_decl.hpp"
14 #include "Thyra_AssertOp.hpp"
15 
16 
17 namespace Thyra {
18 
19 
20 // Inline members only used in implementation
21 
22 
23 template<class Scalar>
24 inline
25 void DefaultMultipliedLinearOp<Scalar>::assertInitialized() const
26 {
27 #ifdef TEUCHOS_DEBUG
28  TEUCHOS_TEST_FOR_EXCEPT( !( numOps() > 0 ) );
29 #endif
30 }
31 
32 
33 template<class Scalar>
34 inline
35 std::string DefaultMultipliedLinearOp<Scalar>::getClassName() const
36 {
38 }
39 
40 
41 template<class Scalar>
42 inline
43 Ordinal DefaultMultipliedLinearOp<Scalar>::getRangeDim() const
44 {
45  return (numOps() > 0 ? this->range()->dim() : 0);
46 }
47 
48 
49 template<class Scalar>
50 inline
51 Ordinal DefaultMultipliedLinearOp<Scalar>::getDomainDim() const
52 {
53  return (numOps() > 0 ? this->domain()->dim() : 0);
54 }
55 
56 
57 // Constructors/initializers/accessors
58 
59 
60 template<class Scalar>
62 {}
63 
64 
65 template<class Scalar>
67  const ArrayView<const RCP<LinearOpBase<Scalar> > > &Ops )
68 {
69  const int nOps = Ops.size();
70  Ops_.resize(nOps);
71  for( int k = 0; k < nOps; ++k )
72  Ops_[k].initialize(Ops[k]);
73  validateOps();
74  setupDefaultObjectLabel();
75 }
76 
77 
78 template<class Scalar>
80  const ArrayView<const RCP<const LinearOpBase<Scalar> > > &Ops )
81 {
82  const int nOps = Ops.size();
83  Ops_.resize(nOps);
84  for( int k = 0; k < nOps; ++k )
85  Ops_[k].initialize(Ops[k]);
86  validateOps();
87  setupDefaultObjectLabel();
88 }
89 
90 
91 template<class Scalar>
93 {
94  Ops_.resize(0);
95  setupDefaultObjectLabel();
96 }
97 
98 
99 // Overridden form MultipliedLinearOpBase
100 
101 
102 template<class Scalar>
104 {
105  return Ops_.size();
106 }
107 
108 
109 template<class Scalar>
111 {
112 #ifdef TEUCHOS_DEBUG
113  TEUCHOS_TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
114 #endif
115  return Ops_[k].isConst();
116 }
117 
118 
119 template<class Scalar>
122 {
123 #ifdef TEUCHOS_DEBUG
124  TEUCHOS_TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
125 #endif
126  return Ops_[k].getNonconstObj();
127 }
128 
129 
130 template<class Scalar>
133 {
134 #ifdef TEUCHOS_DEBUG
135  TEUCHOS_TEST_FOR_EXCEPT( !( 0 <= k && k < numOps() ) );
136 #endif
137  return Ops_[k];
138 }
139 
140 
141 // Overridden from LinearOpBase
142 
143 
144 template<class Scalar>
147 {
148  if (numOps()) {
149  return getOp(0)->range();
150  }
151  return Teuchos::null;
152 }
153 
154 
155 template<class Scalar>
158 {
159  if (numOps()) {
160  return getOp(numOps()-1)->domain();
161  }
162  return Teuchos::null;
163 }
164 
165 
166 template<class Scalar>
169 {
170  return Teuchos::null; // Not supported yet but could be!
171 }
172 
173 
174 // Overridden from Teuchos::Describable
175 
176 
177 template<class Scalar>
179 {
180  std::ostringstream oss;
181  oss << getClassName() << "{numOps="<<numOps()
182  <<",rangeDim=" << getRangeDim()
183  << ",domainDim="<< getDomainDim() <<"}";
184  return oss.str();
185 }
186 
187 template<class Scalar>
189  Teuchos::FancyOStream &out_arg,
190  const Teuchos::EVerbosityLevel verbLevel
191  ) const
192 {
193  using Teuchos::FancyOStream;
194  using Teuchos::OSTab;
195  RCP<FancyOStream> out = rcp(&out_arg,false);
196  OSTab tab(out);
197  const int nOps = Ops_.size();
198  switch(verbLevel) {
200  case Teuchos::VERB_LOW:
201  *out << this->description() << std::endl;
202  break;
204  case Teuchos::VERB_HIGH:
206  {
207  *out << this->description() << std::endl;
208  OSTab tab2(out);
209  *out
210  << "Constituent LinearOpBase objects for M = Op[0]*...*Op[numOps-1]:\n";
211  OSTab tab3(out);
212  for( int k = 0; k < nOps; ++k ) {
213  *out << "Op["<<k<<"] = " << Teuchos::describe(*getOp(k),verbLevel);
214  }
215  break;
216  }
217  default:
218  TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
219  }
220 }
221 
222 
223 // protected
224 
225 
226 // Overridden from LinearOpBase
227 
228 
229 template<class Scalar>
231 {
232  bool overallOpSupported = true;
233  for( int k = 0; k < static_cast<int>(Ops_.size()); ++k )
234  if(!Thyra::opSupported(*getOp(k),M_trans)) overallOpSupported = false;
235  return overallOpSupported;
236  // ToDo: Cache these?
237 }
238 
239 template<class Scalar>
241  const int nOps = Ops_.size();
242  if ((T_k_.size() != Teuchos::as<size_t>(nOps+1)) || ((nOps > 0) && (T_k_[0]->domain()->dim() != dim))) {
243  // op[0]->range
244  // op[0]->domain == op[1]->range
245  // ...
246  // op[nOps-2]->domain == op[nOps-1]->range
247  // op[nOps-1]->domain
248  T_k_.resize(0);
249  for( int k = 0; k < nOps; ++k ) {
250  T_k_.push_back(createMembers(getOp(k)->range(), dim));
251  }
252  T_k_.push_back(createMembers(getOp(nOps-1)->domain(), dim));
253  }
254 }
255 
256 
257 template<class Scalar>
259  const EOpTransp M_trans,
260  const MultiVectorBase<Scalar> &X,
261  const Ptr<MultiVectorBase<Scalar> > &Y,
262  const Scalar alpha,
263  const Scalar beta
264  ) const
265 {
266  using Teuchos::rcpFromPtr;
267  using Teuchos::rcpFromRef;
268 #ifdef TEUCHOS_DEBUG
270  getClassName()+"::apply(...)", *this, M_trans, X, &*Y
271  );
272 #endif // TEUCHOS_DEBUG
273  const int nOps = Ops_.size();
274  const Ordinal m = X.domain()->dim();
275  allocateVecs(m);
276  if( real_trans(M_trans)==NOTRANS ) {
277  //
278  // Y = alpha * M * X + beta*Y
279  // =>
280  // Y = alpha * op(Op[0]) * op(Op[1]) * ... * op(Op[numOps-1]) * X + beta*Y
281  //
282  RCP<MultiVectorBase<Scalar> > T_kp1, T_k; // Temporary propagated between loops
283  for( int k = nOps-1; k >= 0; --k ) {
286  if(k==0) Y_k = rcpFromPtr(Y); else Y_k = T_k = T_k_[k];
287  if(k==nOps-1) X_k = rcpFromRef(X); else X_k = T_kp1;
288  if( k > 0 )
289  Thyra::apply(*getOp(k), M_trans, *X_k, Y_k.ptr());
290  else
291  Thyra::apply(*getOp(k), M_trans, *X_k, Y_k.ptr(), alpha, beta);
292  T_kp1 = T_k;
293  }
294  }
295  else {
296  //
297  // Y = alpha * M' * X + beta*Y
298  // =>
299  // Y = alpha * Op[numOps-1]' * Op[1]' * ... * Op[0]' * X + beta * Y
300  //
301  RCP<MultiVectorBase<Scalar> > T_km1, T_k; // Temporary propagated between loops
302  for( int k = 0; k <= nOps-1; ++k ) {
305  if(k==nOps-1) Y_k = rcpFromPtr(Y); else Y_k = T_k = T_k_[k+1];
306  if(k==0) X_k = rcpFromRef(X); else X_k = T_km1;
307  if( k < nOps-1 )
308  Thyra::apply(*getOp(k), M_trans, *X_k, Y_k.ptr());
309  else
310  Thyra::apply(*getOp(k), M_trans, *X_k, Y_k.ptr(), alpha, beta);
311  T_km1 = T_k;
312  }
313  }
314 }
315 
316 
317 // private
318 
319 
320 template<class Scalar>
322 {
323  using Teuchos::toString;
324 #ifdef TEUCHOS_DEBUG
325  try {
326  const int nOps = Ops_.size();
327  for( int k = 0; k < nOps; ++k ) {
328  TEUCHOS_TEST_FOR_EXCEPT( Ops_[k]().get() == NULL );
329  if( k < nOps-1 ) {
331  getClassName()+"::initialize(...)"
332  ,*Ops_[k],NOTRANS,("Ops["+toString(k)+"]")
333  ,*Ops_[k+1],NOTRANS,("Ops["+toString(k+1)+"]")
334  );
335  }
336  }
337  }
338  catch(...) {
339  uninitialize();
340  throw;
341  }
342 #endif
343 }
344 
345 
346 template<class Scalar>
347 void DefaultMultipliedLinearOp<Scalar>::setupDefaultObjectLabel()
348 {
349  std::ostringstream label;
350  const int nOps = Ops_.size();
351  for( int k = 0; k < nOps; ++k ) {
352  std::string Op_k_label = Ops_[k]->getObjectLabel();
353  if (Op_k_label.length() == 0)
354  Op_k_label = "ANYM";
355  if (k > 0)
356  label << "*";
357  label << "("<<Op_k_label<<")";
358  }
359  this->setObjectLabel(label.str());
360  validateOps();
361 }
362 
363 
364 } // end namespace Thyra
365 
366 
367 //
368 // Nonmember implementations
369 //
370 
371 template<class Scalar>
373 Thyra::nonconstMultiply(
374  const RCP<LinearOpBase<Scalar> > &A,
375  const RCP<LinearOpBase<Scalar> > &B,
376  const std::string &M_label
377  )
378 {
379  using Teuchos::tuple;
380  RCP<DefaultMultipliedLinearOp<Scalar> > multOp =
381  defaultMultipliedLinearOp<Scalar>(tuple(A, B)());
382  if(M_label.length())
383  multOp->setObjectLabel(M_label);
384  return multOp;
385 }
386 
387 
388 template<class Scalar>
390 Thyra::multiply(
391  const RCP<const LinearOpBase<Scalar> > &A,
392  const RCP<const LinearOpBase<Scalar> > &B,
393  const std::string &M_label
394  )
395 {
396  using Teuchos::tuple;
397  RCP<DefaultMultipliedLinearOp<Scalar> > multOp =
398  defaultMultipliedLinearOp<Scalar>(tuple(A, B)());
399  if(M_label.length())
400  multOp->setObjectLabel(M_label);
401  return multOp;
402 }
403 
404 
405 template<class Scalar>
407 Thyra::multiply(
408  const RCP<const LinearOpBase<Scalar> > &A,
409  const RCP<const LinearOpBase<Scalar> > &B,
410  const RCP<const LinearOpBase<Scalar> > &C,
411  const std::string &M_label
412  )
413 {
414  using Teuchos::tuple;
415  RCP<DefaultMultipliedLinearOp<Scalar> > multOp =
416  defaultMultipliedLinearOp<Scalar>(tuple(A, B, C)());
417  if(M_label.length())
418  multOp->setObjectLabel(M_label);
419  return multOp;
420 }
421 
422 
423 //
424 // Explicit instantiation macro
425 //
426 // Must be expanded from within the Thyra namespace!
427 //
428 
429 
430 #define THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_INSTANT(SCALAR) \
431  \
432  template class DefaultMultipliedLinearOp<SCALAR >; \
433  \
434  template RCP<LinearOpBase<SCALAR > > \
435  nonconstMultiply( \
436  const RCP<LinearOpBase<SCALAR > > &A, \
437  const RCP<LinearOpBase<SCALAR > > &B, \
438  const std::string &M_label \
439  ); \
440  \
441  template RCP<const LinearOpBase<SCALAR > > \
442  multiply( \
443  const RCP<const LinearOpBase<SCALAR > > &A, \
444  const RCP<const LinearOpBase<SCALAR > > &B, \
445  const std::string &M_label \
446  ); \
447  \
448  template RCP<const LinearOpBase<SCALAR > > \
449  multiply( \
450  const RCP<const LinearOpBase<SCALAR > > &A, \
451  const RCP<const LinearOpBase<SCALAR > > &B, \
452  const RCP<const LinearOpBase<SCALAR > > &C, \
453  const std::string &M_label \
454  ); \
455 
456 
457 #endif // THYRA_DEFAULT_MULTIPLIED_LINEAR_OP_DEF_HPP
void initialize(int *argc, char ***argv)
#define THYRA_ASSERT_LINEAR_OP_TIMES_LINEAR_OP_SPACES_NAMES(FUNC_NAME, M1, M1_T, M1_N, M2, M2_T, M2_N)
Assert that a linear operator multiplication matches up.
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
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...
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...
DefaultMultipliedLinearOp()
Constructs to uninitialized.
basic_FancyOStream< char > FancyOStream
Use the non-transposed operator.
EOpTransp real_trans(EOpTransp transp)
Return NOTRANS or TRANS for real scalar valued operators and this also is used for determining struct...
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.
bool opSupportedImpl(EOpTransp M_trans) const
Returns true only if all constituent operators support M_trans.
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.
RCP< const LinearOpBase< Scalar > > clone() const
RCP< LinearOpBase< Scalar > > getNonconstOp(const int k)
Ptr< T > ptr() const
Concrete composite LinearOpBase subclass that creates an implicitly multiplied linear operator out of...
virtual std::string description() const
TEUCHOSCORE_LIB_DLL_EXPORT std::string toString(const EVerbosityLevel verbLevel)
Base class for all linear operators.
std::string description() const
Prints just the name DefaultMultipliedLinearOp along with the overall dimensions and the number of co...
virtual RCP< const VectorSpaceBase< Scalar > > domain() const =0
Return a smart pointer for the domain space for this operator.
void applyImpl(const EOpTransp M_trans, const MultiVectorBase< Scalar > &X, const Ptr< MultiVectorBase< Scalar > > &Y, const Scalar alpha, const Scalar beta) const
RCP< const LinearOpBase< Scalar > > getOp(const int k) const
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
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...
std::string toString(const T &t)