Thyra Version of the Day
Loading...
Searching...
No Matches
Thyra_DefaultBlockedLinearOp_def.hpp
1// @HEADER
2// ***********************************************************************
3//
4// Thyra: Interfaces and Support for Abstract Numerical Algorithms
5// Copyright (2004) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Roscoe A. Bartlett (bartlettra@ornl.gov)
38//
39// ***********************************************************************
40// @HEADER
41
42
43#ifndef THYRA_DEFAULT_BLOCKED_LINEAR_OP_DEF_HPP
44#define THYRA_DEFAULT_BLOCKED_LINEAR_OP_DEF_HPP
45
46
47#include "Thyra_DefaultBlockedLinearOp_decl.hpp"
48#include "Thyra_DefaultProductVectorSpace.hpp"
49#include "Thyra_DefaultProductVector.hpp"
50#include "Thyra_DefaultProductMultiVector.hpp"
51#include "Thyra_MultiVectorStdOps.hpp"
52#include "Thyra_VectorStdOps.hpp"
53#include "Thyra_AssertOp.hpp"
54#include "Thyra_ScaledAdjointLinearOpBase.hpp"
55
56
57namespace Thyra {
58
59
60// Constructors
61
62
63template<class Scalar>
65 :numRowBlocks_(0), numColBlocks_(0), blockFillIsActive_(false)
66{}
67
68
69// Overridden from PhysicallyBlockedLinearOpBase
70
71
72template<class Scalar>
74{
75 assertBlockFillIsActive(false);
76 uninitialize();
77 resetStorage(0,0);
78}
79
80
81template<class Scalar>
83 const int numRowBlocks, const int numColBlocks
84 )
85{
86 assertBlockFillIsActive(false);
87 uninitialize();
88 resetStorage(numRowBlocks,numColBlocks);
89}
90
91
92template<class Scalar>
94 const RCP<const ProductVectorSpaceBase<Scalar> > &new_productRange
95 ,const RCP<const ProductVectorSpaceBase<Scalar> > &new_productDomain
96 )
97{
98 using Teuchos::rcp_dynamic_cast;
99 assertBlockFillIsActive(false);
100 uninitialize();
101 productRange_ = new_productRange.assert_not_null();
102 productDomain_ = new_productDomain.assert_not_null();
103 defaultProductRange_ =
104 rcp_dynamic_cast<const DefaultProductVectorSpace<Scalar> >(productRange_);
105 defaultProductDomain_ =
106 rcp_dynamic_cast<const DefaultProductVectorSpace<Scalar> >(productDomain_);
107 // Note: the above spaces must be set before calling the next function!
108 resetStorage(productRange_->numBlocks(), productDomain_->numBlocks());
109}
110
111
112template<class Scalar>
114{
115 return blockFillIsActive_;
116}
117
118
119template<class Scalar>
121 const int i, const int j
122 ) const
123{
124 assertBlockFillIsActive(true);
125 assertBlockRowCol(i,j);
126 return true;
127}
128
129
130template<class Scalar>
132 const int i, const int j
133 ,const RCP<LinearOpBase<Scalar> > &block
134 )
135{
136 setBlockImpl(i, j, block);
137}
138
139
140template<class Scalar>
142 const int i, const int j
143 ,const RCP<const LinearOpBase<Scalar> > &block
144 )
145{
146 setBlockImpl(i, j, block);
147}
148
149
150template<class Scalar>
152{
153
154 using Teuchos::as;
155
156 assertBlockFillIsActive(true);
157
158 // 2009/05/06: rabartl: ToDo: When doing a flexible block fill
159 // (Ops_stack_.size() > 0), we need to assert that all of the block rows and
160 // columns have been filled in. I don't think we do that here.
161
162 // Get the number of block rows and columns
163 if (nonnull(productRange_)) {
164 numRowBlocks_ = productRange_->numBlocks();
165 numColBlocks_ = productDomain_->numBlocks();
166 }
167 else {
168 numRowBlocks_ = rangeBlocks_.size();
169 numColBlocks_ = domainBlocks_.size();
170 // NOTE: Above, whether doing a flexible fill or not, all of the blocks
171 // must be set in order to have a valid filled operator so this
172 // calculation should be correct.
173 }
174
175 // Assert that all of the block rows and columns have at least one entry if
176 // the spaces were not given up front.
177#ifdef TEUCHOS_DEBUG
178 if (is_null(productRange_)) {
179 for (int i = 0; i < numRowBlocks_; ++i) {
181 !rangeBlocks_[i].get(), std::logic_error
182 ,"DefaultBlockedLinearOp<Scalar>::endBlockFill():"
183 " Error, no linear operator block for the i="<<i<<" block row was added"
184 " and we can not complete the block fill!"
185 );
186 }
187 for(int j = 0; j < numColBlocks_; ++j) {
189 !domainBlocks_[j].get(), std::logic_error
190 ,"DefaultBlockedLinearOp<Scalar>::endBlockFill():"
191 " Error, no linear operator block for the j="
192 <<j<<" block column was added"
193 " and we can not complete the block fill!"
194 );
195 }
196 }
197#endif
198
199 // Insert the block LOB objects if doing a flexible fill.
200 if (Ops_stack_.size()) {
201 Ops_.resize(numRowBlocks_*numColBlocks_);
202 for ( int k = 0; k < as<int>(Ops_stack_.size()); ++k ) {
203 const BlockEntry<Scalar> &block_i_j = Ops_stack_[k];
204 Ops_[numRowBlocks_*block_i_j.j + block_i_j.i] = block_i_j.block;
205 }
206 Ops_stack_.resize(0);
207 }
208
209 // Set the product range and domain spaces if not already set
210 if (is_null(productRange_)) {
211 adjustBlockSpaces();
212 defaultProductRange_ = productVectorSpace<Scalar>(rangeBlocks_());
213 defaultProductDomain_ = productVectorSpace<Scalar>(domainBlocks_());
214 productRange_ = defaultProductRange_;
215 productDomain_ = defaultProductDomain_;
216 }
217
218 rangeBlocks_.resize(0);
219 domainBlocks_.resize(0);
220
221 blockFillIsActive_ = false;
222
223}
224
225
226template<class Scalar>
228{
229 productRange_ = Teuchos::null;
230 productDomain_ = Teuchos::null;
231 numRowBlocks_ = 0;
232 numColBlocks_ = 0;
233 Ops_.resize(0);
234 Ops_stack_.resize(0);
235 rangeBlocks_.resize(0);
236 domainBlocks_.resize(0);
237 blockFillIsActive_ = false;
238}
239
240
241// Overridden from BlockedLinearOpBase
242
243
244template<class Scalar>
247{
248 return productRange_;
249}
250
251
252template<class Scalar>
255{
256 return productDomain_;
257}
258
259
260template<class Scalar>
262 const int i, const int j
263 ) const
264{
265 assertBlockFillIsActive(false);
266 assertBlockRowCol(i,j);
267 return true;
268}
269
270
271template<class Scalar>
273 const int i, const int j
274 ) const
275{
276#ifdef TEUCHOS_DEBUG
277 TEUCHOS_TEST_FOR_EXCEPT(!blockExists(i,j));
278#endif
279 assertBlockFillIsActive(false);
280 assertBlockRowCol(i,j);
281 return Ops_[numRowBlocks_*j+i].isConst();
282}
283
284
285template<class Scalar>
288{
289#ifdef TEUCHOS_DEBUG
290 TEUCHOS_TEST_FOR_EXCEPT(!blockExists(i,j));
291#endif
292 assertBlockFillIsActive(false);
293 assertBlockRowCol(i,j);
294 return Ops_[numRowBlocks_*j+i].getNonconstObj();
295}
296
297
298template<class Scalar>
300DefaultBlockedLinearOp<Scalar>::getBlock(const int i, const int j) const
301{
302#ifdef TEUCHOS_DEBUG
303 TEUCHOS_TEST_FOR_EXCEPT(!blockExists(i,j));
304#endif
305 assertBlockFillIsActive(false);
306 assertBlockRowCol(i,j);
307 return Ops_[numRowBlocks_*j+i];
308}
309
310
311// Overridden from LinearOpBase
312
313
314template<class Scalar>
317{
318 return productRange_;
319}
320
321
322template<class Scalar>
325{
326 return productDomain_;
327}
328
329
330template<class Scalar>
333{
334 return Teuchos::null; // ToDo: Implement this when needed!
335}
336
337
338// Overridden from Teuchos::Describable
339
340
341template<class Scalar>
343{
344 assertBlockFillIsActive(false);
345 std::ostringstream oss;
346 oss
348 << "numRowBlocks="<<numRowBlocks_
349 << ",numColBlocks="<<numColBlocks_
350 << "}";
351 return oss.str();
352}
353
354
355template<class Scalar>
357 Teuchos::FancyOStream &out_arg
358 ,const Teuchos::EVerbosityLevel verbLevel
359 ) const
360{
361 using Teuchos::rcpFromRef;
363 using Teuchos::OSTab;
364 assertBlockFillIsActive(false);
365 RCP<FancyOStream> out = rcpFromRef(out_arg);
366 OSTab tab1(out);
367 switch(verbLevel) {
370 *out << this->description() << std::endl;
371 break;
375 {
376 *out
378 << "rangeDim=" << this->range()->dim()
379 << ",domainDim=" << this->domain()->dim()
380 << ",numRowBlocks=" << numRowBlocks_
381 << ",numColBlocks=" << numColBlocks_
382 << "}\n";
383 OSTab tab2(out);
384 *out
385 << "Constituent LinearOpBase objects for M = [ Op[0,0] ..."
386 << " ; ... ; ... Op[numRowBlocks-1,numColBlocks-1] ]:\n";
387 tab2.incrTab();
388 for( int i = 0; i < numRowBlocks_; ++i ) {
389 for( int j = 0; j < numColBlocks_; ++j ) {
390 *out << "Op["<<i<<","<<j<<"] = ";
392 block_i_j = getBlock(i,j);
393 if(block_i_j.get())
394 *out << Teuchos::describe(*getBlock(i,j),verbLevel);
395 else
396 *out << "NULL\n";
397 }
398 }
399 break;
400 }
401 default:
402 TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
403 }
404}
405
406
407// protected
408
409
410// Overridden from LinearOpBase
411
412
413template<class Scalar>
415{
416 bool supported = true;
417 for( int i = 0; i < numRowBlocks_; ++i ) {
418 for( int j = 0; j < numColBlocks_; ++j ) {
420 block_i_j = getBlock(i,j);
421 if( block_i_j.get() && !Thyra::opSupported(*block_i_j,M_trans) )
422 supported = false;
423 }
424 }
425 return supported;
426}
427
428
429template<class Scalar>
431 const EOpTransp M_trans,
432 const MultiVectorBase<Scalar> &X_in,
433 const Ptr<MultiVectorBase<Scalar> > &Y_inout,
434 const Scalar alpha,
435 const Scalar beta
436 ) const
437{
438
439 using Teuchos::rcpFromRef;
441 typedef RCP<MultiVectorBase<Scalar> > MultiVectorPtr;
442 typedef RCP<const MultiVectorBase<Scalar> > ConstMultiVectorPtr;
443 typedef RCP<const LinearOpBase<Scalar> > ConstLinearOpPtr;
444
445#ifdef TEUCHOS_DEBUG
447 "DefaultBlockedLinearOp<Scalar>::apply(...)", *this, M_trans, X_in, &*Y_inout
448 );
449#endif // TEUCHOS_DEBUG
450
451 const bool
452 struct_transp = (real_trans(M_trans)!=NOTRANS); // Structural transpose?
453 const int
454 opNumRowBlocks = ( !struct_transp ? numRowBlocks_ : numColBlocks_ ),
455 opNumColBlocks = ( !struct_transp ? numColBlocks_ : numRowBlocks_ );
456
457 //
458 // Y = alpha * op(M) * X + beta*Y
459 //
460 // =>
461 //
462 // Y[i] = beta+Y[i] + sum(alpha*op(Op)[i,j]*X[j],j=0...opNumColBlocks-1)
463 //
464 // , for i=0...opNumRowBlocks-1
465 //
466
468 defaultProductRange_op = ( real_trans(M_trans)==NOTRANS
469 ? defaultProductRange_ : defaultProductDomain_ ),
470 defaultProductDomain_op = ( real_trans(M_trans)==NOTRANS
471 ? defaultProductDomain_ : defaultProductRange_ );
472
474 X = castOrCreateSingleBlockProductMultiVector<Scalar>(
475 defaultProductDomain_op, rcpFromRef(X_in));
477 Y = nonconstCastOrCreateSingleBlockProductMultiVector<Scalar>(
478 defaultProductRange_op, rcpFromPtr(Y_inout));
479
480 for( int i = 0; i < opNumRowBlocks; ++i ) {
481 MultiVectorPtr Y_i = Y->getNonconstMultiVectorBlock(i);
482 for( int j = 0; j < opNumColBlocks; ++j ) {
483 ConstLinearOpPtr
484 Op_i_j = ( !struct_transp ? getBlock(i,j) : getBlock(j,i) );
485 ConstMultiVectorPtr
486 X_j = X->getMultiVectorBlock(j);
487 if(j==0) {
488 if (nonnull(Op_i_j))
489 Thyra::apply(*Op_i_j, M_trans,* X_j, Y_i.ptr(), alpha, beta);
490 else
491 scale(beta, Y_i.ptr());
492 }
493 else {
494 if (nonnull(Op_i_j))
495 Thyra::apply(*Op_i_j, M_trans, *X_j, Y_i.ptr(), alpha, ST::one());
496 }
497 }
498 }
499}
500
501// Overridden from RowStatLinearOpBase
502
503template<class Scalar>
504bool
506 const RowStatLinearOpBaseUtils::ERowStat row_stat) const
507{
508 using Teuchos::rcpFromRef;
509 using Teuchos::rcp_dynamic_cast;
510 using Teuchos::dyn_cast;
511 //typedef Teuchos::ScalarTraits<Scalar> ST; // unused
512 typedef RowStatLinearOpBase<Scalar> RowStatOp;
513 typedef RCP<const LinearOpBase<Scalar> > ConstLinearOpPtr;
514 typedef const LinearOpBase<Scalar> ConstLinearOp;
515
516 // Figure out what needs to be check for each sub block to compute
517 // the require row stat
518 RowStatLinearOpBaseUtils::ERowStat
519 subblk_stat = RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM,
520 subblk_trans_stat = RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM;
521 switch (row_stat) {
522 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
523 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
524 subblk_stat = RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM;
525 subblk_trans_stat = RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM;
526 break;
527 case RowStatLinearOpBaseUtils::ROW_STAT_INV_COL_SUM:
528 case RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM:
529 subblk_stat = RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM;
530 subblk_trans_stat = RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM;
531 break;
532 default:
534 }
535
536 // check each sub block for compatibility (null means zero,
537 // automatically compatible)
538 for( int i = 0; i < numRowBlocks_; ++i ) {
539 for( int j = 0; j < numColBlocks_; ++j ) {
540 ConstLinearOpPtr Op_i_j = getBlock(i,j);
541
542 if (nonnull(Op_i_j)) {
543 // pull out adjoint, and scaling
544 ConstLinearOp * Orig_i_j = 0;
545 Scalar scalar = 1.0;
546 EOpTransp transp = NOTRANS;
547 Thyra::unwrap(*Op_i_j,&scalar,&transp,&Orig_i_j);
548
549 const RowStatOp & row_stat_op = Teuchos::dyn_cast<const RowStatOp>(*Orig_i_j);
550
551 // sub block must also support the required row stat operation
552 RowStatLinearOpBaseUtils::ERowStat stat = subblk_stat;
553 if(transp==NOTRANS || transp==CONJ)
554 stat = subblk_stat;
555 else if(transp==TRANS || transp==CONJTRANS)
556 stat = subblk_trans_stat;
557
558 if(!row_stat_op.rowStatIsSupported(stat))
559 return false;
560 }
561 // else: sub block is null, "0" is good enough
562 }
563 }
564
565 return true;
566}
567
568template<class Scalar>
569void
571 const RowStatLinearOpBaseUtils::ERowStat row_stat,
572 const Teuchos::Ptr<VectorBase< Scalar> > &rowStatVec) const
573{
574 using Teuchos::rcpFromRef;
575 using Teuchos::rcpFromPtr;
576 using Teuchos::rcp_dynamic_cast;
577 using Teuchos::dyn_cast;
579 typedef RowStatLinearOpBase<Scalar> RowStatOp;
580 typedef RCP<const LinearOpBase<Scalar> > ConstLinearOpPtr;
581 typedef const LinearOpBase<Scalar> ConstLinearOp;
582 typedef RCP<VectorBase<Scalar> > VectorPtr;
583
584 // Figure out what needs to be check for each sub block to compute
585 // the require row stat
586 RowStatLinearOpBaseUtils::ERowStat
587 subblk_stat = RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM,
588 subblk_trans_stat = RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM;
589 switch (row_stat) {
590 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
591 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
592 subblk_stat = RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM;
593 subblk_trans_stat = RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM;
594 break;
595 case RowStatLinearOpBaseUtils::ROW_STAT_INV_COL_SUM:
596 case RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM:
597 subblk_stat = RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM;
598 subblk_trans_stat = RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM;
599 break;
600 default:
602 }
603
605 Y = rcp_dynamic_cast<ProductVectorBase<Scalar> >(rcpFromPtr(rowStatVec));
606
607 // using sub block row stat capability interrogate each for
608 // its constribution
609 for( int i = 0; i < numRowBlocks_; ++i ) {
610 VectorPtr blk_vec = Y->getNonconstVectorBlock(i);
611 put_scalar (ST::zero (), blk_vec.ptr ()); // clear vector just in case
612
613 for( int j = 0; j < numColBlocks_; ++j ) {
614 ConstLinearOpPtr Op_i_j = getBlock(i,j);
615
616 VectorPtr tmp_vec = createMember(Op_i_j->range());
617
618 put_scalar (ST::zero (), tmp_vec.ptr ()); // clear vector just in case
619
620 if (nonnull(Op_i_j)) {
621 // pull out adjoint, and scaling
622 ConstLinearOp * Orig_i_j = 0;
623 Scalar scalar = 1.0;
624 EOpTransp transp = NOTRANS;
625 Thyra::unwrap(*Op_i_j,&scalar,&transp,&Orig_i_j);
626
627 const RowStatOp & row_stat_op = Teuchos::dyn_cast<const RowStatOp>(*Orig_i_j);
628
629 // sub block must also support the required row stat operation
630 if(transp==NOTRANS || transp==CONJ)
631 row_stat_op.getRowStat(subblk_stat,tmp_vec.ptr());
632 else if(transp==TRANS || transp==CONJTRANS)
633 row_stat_op.getRowStat(subblk_trans_stat,tmp_vec.ptr());
634 else
635 { TEUCHOS_ASSERT(false); }
636
637 // some the temporary into the block vector
638 Vp_V(blk_vec.ptr(),*tmp_vec);
639 }
640 }
641 }
642
643 // do post processing as needed (take the inverse currently
644 switch (row_stat) {
645 case RowStatLinearOpBaseUtils::ROW_STAT_INV_ROW_SUM:
646 case RowStatLinearOpBaseUtils::ROW_STAT_INV_COL_SUM:
647 reciprocal(*rowStatVec,rowStatVec.ptr());
648 case RowStatLinearOpBaseUtils::ROW_STAT_ROW_SUM:
649 case RowStatLinearOpBaseUtils::ROW_STAT_COL_SUM:
650 break;
651 default:
653 }
654}
655
656// Overridden from ScaledLinearOpBase
657
658template<class Scalar>
659bool
661{
662 using Teuchos::rcp_dynamic_cast;
663 using Teuchos::dyn_cast;
664 typedef RCP<const LinearOpBase<Scalar> > LinearOpPtr;
665 typedef const LinearOpBase<Scalar> LinearOp;
666 typedef const ScaledLinearOpBase<Scalar> ScaledOp;
667
668 bool supported = true;
669 for( int i = 0; i < numRowBlocks_; ++i ) {
670 for( int j = 0; j < numColBlocks_; ++j ) {
671 LinearOpPtr Op_i_j = getBlock(i,j);
672
673 EOpTransp transp = NOTRANS;
674
675 if (nonnull(Op_i_j)) {
676 // pull out adjoint, and scaling
677 LinearOp * Orig_i_j = 0;
678 Scalar scalar = 1.0;
679 Thyra::unwrap(*Op_i_j,&scalar,&transp,&Orig_i_j);
680
681 ScaledOp & scaled_op = Teuchos::dyn_cast<ScaledOp>(*Orig_i_j);
682
683 if(transp==NOTRANS || transp==CONJ)
684 supported &= scaled_op.supportsScaleLeft();
685 else if(transp==TRANS || transp==CONJTRANS)
686 supported &= scaled_op.supportsScaleRight();
687 }
688 }
689 }
690
691 return supported;
692}
693
694template<class Scalar>
695bool
697{
698 using Teuchos::rcp_dynamic_cast;
699 using Teuchos::dyn_cast;
700 typedef RCP<const LinearOpBase<Scalar> > LinearOpPtr;
701 typedef const LinearOpBase<Scalar> LinearOp;
702 typedef const ScaledLinearOpBase<Scalar> ScaledOp;
703
704 bool supported = true;
705 for( int i = 0; i < numRowBlocks_; ++i ) {
706 for( int j = 0; j < numColBlocks_; ++j ) {
707 LinearOpPtr Op_i_j = getBlock(i,j);
708
709 if (nonnull(Op_i_j)) {
710 // pull out adjoint, and scaling
711 LinearOp * Orig_i_j = 0;
712 Scalar scalar = 1.0;
713 EOpTransp transp = NOTRANS;
714 Thyra::unwrap(*Op_i_j,&scalar,&transp,&Orig_i_j);
715
716 ScaledOp & scaled_op = Teuchos::dyn_cast<ScaledOp>(*Orig_i_j);
717
718 if(transp==NOTRANS || transp==CONJ)
719 supported &= scaled_op.supportsScaleRight();
720 else if(transp==TRANS || transp==CONJTRANS)
721 supported &= scaled_op.supportsScaleLeft();
722 }
723 }
724 }
725
726 return supported;
727}
728
729template<class Scalar>
730void
732 const VectorBase< Scalar > &row_scaling)
733{
734 using Teuchos::dyn_cast;
735 using Teuchos::rcp_dynamic_cast;
736 typedef ScaledLinearOpBase<Scalar> ScaledOp;
737 typedef RCP<LinearOpBase<Scalar> > LinearOpPtr;
738 typedef RCP<const VectorBase<Scalar> > VectorPtr;
739
741 Y = dyn_cast<const ProductVectorBase<Scalar> >(row_scaling);
742
743 // using sub block row stat capability interrogate each for
744 // its constribution
745 for( int i = 0; i < numRowBlocks_; ++i ) {
746 VectorPtr blk_vec = Y.getVectorBlock(i);
747
748 for( int j = 0; j < numColBlocks_; ++j ) {
749 LinearOpPtr Op_i_j = getNonconstBlock(i,j);
750
751 if (nonnull(Op_i_j)) {
752 // pull out adjoint, and scaling
753 LinearOpPtr Orig_i_j;
754 EOpTransp transp = NOTRANS;
755
756 {
758 = rcp_dynamic_cast<ScaledAdjointLinearOpBase<Scalar> >(Op_i_j);
759 if(nonnull(saOp)) {
760 transp = saOp->overallTransp();
761 Orig_i_j = saOp->getNonconstOrigOp();
762 }
763 else
764 Orig_i_j = Op_i_j; // stick with the original
765 }
766
767 RCP<ScaledOp> scaled_op = rcp_dynamic_cast<ScaledOp>(Orig_i_j);
768
769 // sub block must support a row stat operation
770 TEUCHOS_ASSERT(scaled_op!=Teuchos::null); // guranteed by compatibility check
771
772 // sub block must also support the required row stat operation
773 if(transp==NOTRANS || transp==CONJ)
774 scaled_op->scaleLeft(*blk_vec);
775 else if(transp==TRANS || transp==CONJTRANS)
776 scaled_op->scaleRight(*blk_vec);
777 }
778 }
779 }
780}
781
782template<class Scalar>
783void
785 const VectorBase< Scalar > &col_scaling)
786{
787 using Teuchos::dyn_cast;
788 using Teuchos::rcp_dynamic_cast;
789 typedef ScaledLinearOpBase<Scalar> ScaledOp;
790 typedef RCP<LinearOpBase<Scalar> > LinearOpPtr;
791 typedef RCP<const VectorBase<Scalar> > VectorPtr;
792
794 Y = dyn_cast<const ProductVectorBase<Scalar> >(col_scaling);
795
796 // using sub block row stat capability interrogate each for
797 // its constribution
798 for( int j = 0; j < numColBlocks_; ++j ) {
799 VectorPtr blk_vec = Y.getVectorBlock(j);
800
801 for( int i = 0; i < numRowBlocks_; ++i ) {
802 LinearOpPtr Op_i_j = getNonconstBlock(i,j);
803
804 if (nonnull(Op_i_j)) {
805 // pull out adjoint, and scaling
806 LinearOpPtr Orig_i_j;
807 EOpTransp transp = NOTRANS;
808
809 {
811 = rcp_dynamic_cast<ScaledAdjointLinearOpBase<Scalar> >(Op_i_j);
812 if(nonnull(saOp)) {
813 transp = saOp->overallTransp();
814 Orig_i_j = saOp->getNonconstOrigOp();
815 }
816 else
817 Orig_i_j = Op_i_j; // stick with the original
818 }
819
820 RCP<ScaledOp> scaled_op = rcp_dynamic_cast<ScaledOp>(Orig_i_j);
821
822 // sub block must support a row stat operation
823 TEUCHOS_ASSERT(scaled_op!=Teuchos::null); // guranteed by compatibility check
824
825 // sub block must also support the required row stat operation
826 if(transp==NOTRANS || transp==CONJ)
827 scaled_op->scaleRight(*blk_vec);
828 else if(transp==TRANS || transp==CONJTRANS)
829 scaled_op->scaleLeft(*blk_vec);
830 }
831 }
832 }
833}
834
835// private
836
837
838template<class Scalar>
840 const int numRowBlocks, const int numColBlocks
841 )
842{
843 numRowBlocks_ = numRowBlocks;
844 numColBlocks_ = numColBlocks;
845 Ops_.resize(numRowBlocks_*numColBlocks_);
846 if (is_null(productRange_)) {
847 rangeBlocks_.resize(numRowBlocks);
848 domainBlocks_.resize(numColBlocks);
849 }
850 blockFillIsActive_ = true;
851}
852
853
854template<class Scalar>
855void DefaultBlockedLinearOp<Scalar>::assertBlockFillIsActive(
856 bool wantedValue
857 ) const
858{
859#ifdef TEUCHOS_DEBUG
860 TEUCHOS_TEST_FOR_EXCEPT(!(blockFillIsActive_==wantedValue));
861#else
862 (void)wantedValue;
863#endif
864}
865
866
867template<class Scalar>
868void DefaultBlockedLinearOp<Scalar>::assertBlockRowCol(
869 const int i, const int j
870 ) const
871{
872#ifdef TEUCHOS_DEBUG
874 !( 0 <= i ), std::logic_error
875 ,"Error, i="<<i<<" is invalid!"
876 );
878 !( 0 <= j ), std::logic_error
879 ,"Error, j="<<j<<" is invalid!"
880 );
881 // Only validate upper range if the number of row and column blocks is
882 // fixed!
883 if(Ops_.size()) {
885 !( 0 <= i && i < numRowBlocks_ ), std::logic_error
886 ,"Error, i="<<i<<" does not fall in the range [0,"<<numRowBlocks_-1<<"]!"
887 );
889 !( 0 <= j && j < numColBlocks_ ), std::logic_error
890 ,"Error, j="<<j<<" does not fall in the range [0,"<<numColBlocks_-1<<"]!"
891 );
892 }
893#else
894 (void)i;
895 (void)j;
896#endif
897}
898
899
900template<class Scalar>
901void DefaultBlockedLinearOp<Scalar>::setBlockSpaces(
902 const int i, const int j, const LinearOpBase<Scalar> &block
903 )
904{
905 using Teuchos::toString;
906 assertBlockFillIsActive(true);
907 assertBlockRowCol(i,j);
908
909 // Validate that if the vector space block is already set that it is
910 // compatible with the block that is being set.
911 if( i < numRowBlocks_ && j < numColBlocks_ ) {
912#ifdef TEUCHOS_DEBUG
913 RCP<const VectorSpaceBase<Scalar> >
914 rangeBlock = (
915 productRange_.get()
916 ? productRange_->getBlock(i)
917 : rangeBlocks_[i]
918 ),
919 domainBlock = (
920 productDomain_.get()
921 ? productDomain_->getBlock(j)
922 : domainBlocks_[j]
923 );
924 if(rangeBlock.get()) {
926 "DefaultBlockedLinearOp<Scalar>::setBlockSpaces(i,j,block):\n\n"
927 "Adding block: " + block.description(),
928 *rangeBlock,("(*productRange->getBlock("+toString(i)+"))"),
929 *block.range(),("(*block["+toString(i)+","+toString(j)+"].range())")
930 );
931 }
932 if(domainBlock.get()) {
934 "DefaultBlockedLinearOp<Scalar>::setBlockSpaces(i,j,block):\n\n"
935 "Adding block: " + block.description(),
936 *domainBlock,("(*productDomain->getBlock("+toString(j)+"))"),
937 *block.domain(),("(*block["+toString(i)+","+toString(j)+"].domain())")
938 );
939 }
940#endif // TEUCHOS_DEBUG
941 }
942
943 // Add spaces missing range and domain space blocks if we are doing a
944 // flexible fill (otherwise these loops will not be executed)
945 for( int k = numRowBlocks_; k <= i; ++k )
946 rangeBlocks_.push_back(Teuchos::null);
947 for( int k = numColBlocks_; k <= j; ++k )
948 domainBlocks_.push_back(Teuchos::null);
949
950 // Set the incoming range and domain blocks if not already set
951 if(!productRange_.get()) {
952 if(!rangeBlocks_[i].get())
953 rangeBlocks_[i] = block.range().assert_not_null();
954 if(!domainBlocks_[j].get()) {
955 domainBlocks_[j] = block.domain().assert_not_null();
956 }
957 }
958
959 // Update the current number of row and columns blocks if doing a flexible
960 // fill.
961 if(!Ops_.size()) {
962 numRowBlocks_ = rangeBlocks_.size();
963 numColBlocks_ = domainBlocks_.size();
964 }
965
966}
967
968
969template<class Scalar>
970template<class LinearOpType>
971void DefaultBlockedLinearOp<Scalar>::setBlockImpl(
972 const int i, const int j,
973 const RCP<LinearOpType> &block
974 )
975{
976 setBlockSpaces(i, j, *block);
977 if (Ops_.size()) {
978 // We are doing a fill with a fixed number of row and column blocks so we
979 // can just set this.
980 Ops_[numRowBlocks_*j+i] = block;
981 }
982 else {
983 // We are doing a flexible fill so add the block to the stack of blocks or
984 // replace a block that already exists.
985 bool foundBlock = false;
986 for( unsigned int k = 0; k < Ops_stack_.size(); ++k ) {
987 BlockEntry<Scalar> &block_i_j = Ops_stack_[k];
988 if( block_i_j.i == i && block_i_j.j == j ) {
989 block_i_j.block = block;
990 foundBlock = true;
991 break;
992 }
993 }
994 if(!foundBlock)
995 Ops_stack_.push_back(BlockEntry<Scalar>(i,j,block));
996 }
997}
998
999
1000template<class Scalar>
1001void DefaultBlockedLinearOp<Scalar>::adjustBlockSpaces()
1002{
1003
1004#ifdef TEUCHOS_DEBUG
1005 TEUCHOS_ASSERT_INEQUALITY(Ops_.size(), !=, 0);
1006#endif
1007
1008 //
1009 // Loop through the rows and columns looking for rows with mixed
1010 // single-space range and/or domain spaces on operators and set the single
1011 // spaces as the block space if it exists.
1012 //
1013 // NOTE: Once we get here, we can safely assume that all of the operators
1014 // are compatible w.r.t. their spaces so if there are rows and/or columns
1015 // with mixed product and single vector spaces that we can just pick the
1016 // single vector space for the whole row and/or column.
1017 //
1018
1019 // Adjust blocks in the range space
1020 for (int i = 0; i < numRowBlocks_; ++i) {
1021 for (int j = 0; j < numColBlocks_; ++j) {
1022 const RCP<const LinearOpBase<Scalar> >
1023 op_i_j = Ops_[numRowBlocks_*j+i];
1024 if (is_null(op_i_j))
1025 continue;
1026 const RCP<const VectorSpaceBase<Scalar> > range_i_j = op_i_j->range();
1027 if (is_null(productVectorSpaceBase<Scalar>(range_i_j, false))) {
1028 rangeBlocks_[i] = range_i_j;
1029 break;
1030 }
1031 }
1032 }
1033
1034 // Adjust blocks in the domain space
1035 for (int j = 0; j < numColBlocks_; ++j) {
1036 for (int i = 0; i < numRowBlocks_; ++i) {
1037 const RCP<const LinearOpBase<Scalar> >
1038 op_i_j = Ops_[numRowBlocks_*j+i];
1039 if (is_null(op_i_j))
1040 continue;
1041 const RCP<const VectorSpaceBase<Scalar> >
1042 domain_i_j = op_i_j->domain();
1043 if (is_null(productVectorSpaceBase<Scalar>(domain_i_j, false))) {
1044 domainBlocks_[j] = domain_i_j;
1045 break;
1046 }
1047 }
1048 }
1049
1050}
1051
1052
1053} // namespace Thyra
1054
1055
1056template<class Scalar>
1058Thyra::defaultBlockedLinearOp()
1059{
1060 return Teuchos::rcp(new DefaultBlockedLinearOp<Scalar>());
1061}
1062
1063
1064template<class Scalar>
1066Thyra::block1x1(
1067 const RCP<const LinearOpBase<Scalar> > &A00,
1068 const std::string &label
1069 )
1070{
1071 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1072 M = defaultBlockedLinearOp<Scalar>();
1073 M->beginBlockFill(1,1);
1074 M->setBlock(0, 0, A00);
1075 M->endBlockFill();
1076 if (label.length())
1077 M->setObjectLabel(label);
1078 return M;
1079}
1080
1081
1082template<class Scalar>
1084Thyra::block1x2(
1085 const RCP<const LinearOpBase<Scalar> > &A00,
1086 const RCP<const LinearOpBase<Scalar> > &A01,
1087 const std::string &label
1088 )
1089{
1090 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1091 M = defaultBlockedLinearOp<Scalar>();
1092 M->beginBlockFill(1,2);
1093 if(A00.get()) M->setBlock(0,0,A00);
1094 if(A01.get()) M->setBlock(0,1,A01);
1095 M->endBlockFill();
1096 if (label.length())
1097 M->setObjectLabel(label);
1098 return M;
1099}
1100
1101
1102template<class Scalar>
1104Thyra::block2x1(
1105 const RCP<const LinearOpBase<Scalar> > &A00,
1106 const RCP<const LinearOpBase<Scalar> > &A10,
1107 const std::string &label
1108 )
1109{
1110 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1111 M = defaultBlockedLinearOp<Scalar>();
1112 M->beginBlockFill(2,1);
1113 if(A00.get()) M->setBlock(0,0,A00);
1114 if(A10.get()) M->setBlock(1,0,A10);
1115 M->endBlockFill();
1116 if (label.length())
1117 M->setObjectLabel(label);
1118 return M;
1119}
1120
1121
1122template<class Scalar>
1124Thyra::block2x2(
1125 const RCP<const LinearOpBase<Scalar> > &A00,
1126 const RCP<const LinearOpBase<Scalar> > &A01,
1127 const RCP<const LinearOpBase<Scalar> > &A10,
1128 const RCP<const LinearOpBase<Scalar> > &A11,
1129 const std::string &label
1130 )
1131{
1132 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1133 M = defaultBlockedLinearOp<Scalar>();
1134 M->beginBlockFill(2,2);
1135 if(A00.get()) M->setBlock(0,0,A00);
1136 if(A01.get()) M->setBlock(0,1,A01);
1137 if(A10.get()) M->setBlock(1,0,A10);
1138 if(A11.get()) M->setBlock(1,1,A11);
1139 M->endBlockFill();
1140 if (label.length())
1141 M->setObjectLabel(label);
1142 return M;
1143}
1144
1145
1146template<class Scalar>
1148Thyra::nonconstBlock1x1(
1149 const RCP<LinearOpBase<Scalar> > &A00,
1150 const std::string &label
1151 )
1152{
1153 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1154 M = defaultBlockedLinearOp<Scalar>();
1155 M->beginBlockFill(1, 1);
1156 M->setNonconstBlock(0, 0, A00);
1157 M->endBlockFill();
1158 if (label.length())
1159 M->setObjectLabel(label);
1160 return M;
1161}
1162
1163
1164template<class Scalar>
1166Thyra::nonconstBlock1x2(
1167 const RCP<LinearOpBase<Scalar> > &A00,
1168 const RCP<LinearOpBase<Scalar> > &A01,
1169 const std::string &label
1170 )
1171{
1172 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1173 M = defaultBlockedLinearOp<Scalar>();
1174 M->beginBlockFill(1,2);
1175 if(A00.get()) M->setNonconstBlock(0,0,A00);
1176 if(A01.get()) M->setNonconstBlock(0,1,A01);
1177 M->endBlockFill();
1178 if (label.length())
1179 M->setObjectLabel(label);
1180 return M;
1181}
1182
1183
1184template<class Scalar>
1186Thyra::nonconstBlock2x1(
1187 const RCP<LinearOpBase<Scalar> > &A00,
1188 const RCP<LinearOpBase<Scalar> > &A10,
1189 const std::string &label
1190 )
1191{
1192 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1193 M = defaultBlockedLinearOp<Scalar>();
1194 M->beginBlockFill(2,1);
1195 if(A00.get()) M->setNonconstBlock(0,0,A00);
1196 if(A10.get()) M->setNonconstBlock(1,0,A10);
1197 M->endBlockFill();
1198 if (label.length())
1199 M->setObjectLabel(label);
1200 return M;
1201}
1202
1203
1204template<class Scalar>
1206Thyra::nonconstBlock2x2(
1207 const RCP<LinearOpBase<Scalar> > &A00,
1208 const RCP<LinearOpBase<Scalar> > &A01,
1209 const RCP<LinearOpBase<Scalar> > &A10,
1210 const RCP<LinearOpBase<Scalar> > &A11,
1211 const std::string &label
1212 )
1213{
1214 RCP<PhysicallyBlockedLinearOpBase<Scalar> >
1215 M = defaultBlockedLinearOp<Scalar>();
1216 M->beginBlockFill(2,2);
1217 if(A00.get()) M->setNonconstBlock(0,0,A00);
1218 if(A01.get()) M->setNonconstBlock(0,1,A01);
1219 if(A10.get()) M->setNonconstBlock(1,0,A10);
1220 if(A11.get()) M->setNonconstBlock(1,1,A11);
1221 M->endBlockFill();
1222 if (label.length())
1223 M->setObjectLabel(label);
1224 return M;
1225}
1226
1227
1228//
1229// Explicit instantiation macro
1230//
1231// Must be expanded from within the Thyra namespace!
1232//
1233
1234
1235#define THYRA_DEFAULT_BLOCKED_LINEAR_OP_INSTANT(SCALAR) \
1236 \
1237 template class DefaultBlockedLinearOp<SCALAR >; \
1238 \
1239 template RCP<DefaultBlockedLinearOp<SCALAR > > \
1240 defaultBlockedLinearOp<SCALAR >(); \
1241 \
1242 template RCP<const LinearOpBase<SCALAR > > \
1243 block1x1( \
1244 const RCP<const LinearOpBase<SCALAR > > &A00, \
1245 const std::string &label \
1246 ); \
1247 \
1248 template RCP<const LinearOpBase<SCALAR > > \
1249 block1x2( \
1250 const RCP<const LinearOpBase<SCALAR > > &A00, \
1251 const RCP<const LinearOpBase<SCALAR > > &A01, \
1252 const std::string &label \
1253 ); \
1254 \
1255 template RCP<const LinearOpBase<SCALAR > > \
1256 block2x1( \
1257 const RCP<const LinearOpBase<SCALAR > > &A00, \
1258 const RCP<const LinearOpBase<SCALAR > > &A10, \
1259 const std::string &label \
1260 ); \
1261 \
1262 template RCP<const LinearOpBase<SCALAR > > \
1263 block2x2( \
1264 const RCP<const LinearOpBase<SCALAR > > &A00, \
1265 const RCP<const LinearOpBase<SCALAR > > &A01, \
1266 const RCP<const LinearOpBase<SCALAR > > &A10, \
1267 const RCP<const LinearOpBase<SCALAR > > &A11, \
1268 const std::string &label \
1269 ); \
1270 \
1271 template RCP<LinearOpBase<SCALAR > > \
1272 nonconstBlock1x1( \
1273 const RCP<LinearOpBase<SCALAR > > &A00, \
1274 const std::string &label \
1275 ); \
1276 \
1277 template RCP<LinearOpBase<SCALAR > > \
1278 nonconstBlock1x2( \
1279 const RCP<LinearOpBase<SCALAR > > &A00, \
1280 const RCP<LinearOpBase<SCALAR > > &A01, \
1281 const std::string &label \
1282 ); \
1283 \
1284 template RCP<LinearOpBase<SCALAR > > \
1285 nonconstBlock2x1( \
1286 const RCP<LinearOpBase<SCALAR > > &A00, \
1287 const RCP<LinearOpBase<SCALAR > > &A10, \
1288 const std::string &label \
1289 ); \
1290 \
1291 template RCP<LinearOpBase<SCALAR > > \
1292 nonconstBlock2x2( \
1293 const RCP<LinearOpBase<SCALAR > > &A00, \
1294 const RCP<LinearOpBase<SCALAR > > &A01, \
1295 const RCP<LinearOpBase<SCALAR > > &A10, \
1296 const RCP<LinearOpBase<SCALAR > > &A11, \
1297 const std::string &label \
1298 );
1299
1300
1301#endif // THYRA_DEFAULT_BLOCKED_LINEAR_OP_DEF_HPP
virtual std::string description() const
T * get() const
Concrete composite LinearOpBase subclass that creates single linear operator object out of a set of c...
Teuchos::RCP< const VectorSpaceBase< Scalar > > domain() const
bool blockIsConst(const int i, const int j) const
virtual void scaleRightImpl(const VectorBase< Scalar > &col_scaling)
void applyImpl(const EOpTransp M_trans, const MultiVectorBase< Scalar > &X, const Ptr< MultiVectorBase< Scalar > > &Y, const Scalar alpha, const Scalar beta) const
bool acceptsBlock(const int i, const int j) const
Teuchos::RCP< const VectorSpaceBase< Scalar > > range() const
virtual bool rowStatIsSupportedImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat) const
Teuchos::RCP< LinearOpBase< Scalar > > getNonconstBlock(const int i, const int j)
Teuchos::RCP< const LinearOpBase< Scalar > > getBlock(const int i, const int j) const
bool blockExists(const int i, const int j) const
virtual void scaleLeftImpl(const VectorBase< Scalar > &row_scaling)
void setNonconstBlock(const int i, const int j, const Teuchos::RCP< LinearOpBase< Scalar > > &block)
Teuchos::RCP< const ProductVectorSpaceBase< Scalar > > productDomain() const
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Prints the details about the constituent linear operators.
Teuchos::RCP< const ProductVectorSpaceBase< Scalar > > productRange() const
virtual void getRowStatImpl(const RowStatLinearOpBaseUtils::ERowStat rowStat, const Teuchos::Ptr< VectorBase< Scalar > > &rowStatVec) const
void setBlock(const int i, const int j, const Teuchos::RCP< const LinearOpBase< Scalar > > &block)
std::string description() const
Prints just the name DefaultBlockedLinearOp along with the overall dimensions and the number of const...
Teuchos::RCP< const LinearOpBase< Scalar > > clone() const
bool opSupportedImpl(EOpTransp M_trans) const
Returns true only if all constituent operators support M_trans.
Base class for all linear operators.
Interface for a collection of column vectors called a multi-vector.
Base interface for product vectors.
virtual RCP< const VectorBase< Scalar > > getVectorBlock(const int k) const =0
Returns a non-persisting const view of the (zero-based) kth block vector.
Interface for exxtracting row statistics as a VectorBase from a supporting LinearOpBase object.
Applies left or right sclaing to the linear operator.
Abstract interface for finite-dimensional dense vectors.
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define TEUCHOS_ASSERT_INEQUALITY(val1, comp, val2)
bool is_null(const std::shared_ptr< T > &p)
#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_VEC_SPACES_NAMES(FUNC_NAME, VS1, VS1_NAME, VS2, VS2_NAME)
Helper assertion macro.
void unwrap(const LinearOpBase< Scalar > &Op, Scalar *scalar, EOpTransp *transp, const LinearOpBase< Scalar > **origOp)
Extract the overallScalar, overallTransp and const origOp from a const LinearOpBase object.
EOpTransp
Enumeration for determining how a linear operator is applied. `*.
const char * toString(EConj conj)
Return a string name for a EOpTransp value. `*.
EOpTransp real_trans(EOpTransp transp)
Return NOTRANS or TRANS for real scalar valued operators and this also is used for determining struct...
@ TRANS
Use the transposed operator.
@ NOTRANS
Use the non-transposed operator.
@ CONJTRANS
Use the transposed operator with complex-conjugate clements (same as TRANS for real scalar types).
@ CONJ
Use the non-transposed operator with complex-conjugate elements (same as NOTRANS for real scalar type...
TypeTo as(const TypeFrom &t)
T_To & dyn_cast(T_From &from)
std::string toString(const T &t)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)