47 #include "Teko_Config.h"
51 #include "Thyra_MultiVectorStdOps.hpp"
52 #include "Thyra_ZeroLinearOpBase.hpp"
53 #include "Thyra_DefaultDiagonalLinearOp.hpp"
54 #include "Thyra_DefaultAddedLinearOp.hpp"
55 #include "Thyra_EpetraExtDiagScaledMatProdTransformer.hpp"
56 #include "Thyra_EpetraExtDiagScalingTransformer.hpp"
57 #include "Thyra_EpetraExtAddTransformer.hpp"
58 #include "Thyra_DefaultScaledAdjointLinearOp.hpp"
59 #include "Thyra_DefaultMultipliedLinearOp.hpp"
60 #include "Thyra_DefaultZeroLinearOp.hpp"
61 #include "Thyra_DefaultProductMultiVector.hpp"
62 #include "Thyra_DefaultProductVectorSpace.hpp"
63 #include "Thyra_MultiVectorStdOps.hpp"
64 #include "Thyra_VectorStdOps.hpp"
65 #include "Thyra_SpmdVectorBase.hpp"
66 #include "Thyra_get_Epetra_Operator.hpp"
67 #include "Thyra_EpetraThyraWrappers.hpp"
68 #include "Thyra_EpetraOperatorWrapper.hpp"
69 #include "Thyra_EpetraLinearOp.hpp"
72 #include "Teuchos_Array.hpp"
75 #include "Epetra_Operator.h"
76 #include "Epetra_CrsGraph.h"
77 #include "Epetra_CrsMatrix.h"
78 #include "Epetra_Vector.h"
79 #include "Epetra_Map.h"
81 #include "EpetraExt_Transpose_RowMatrix.h"
82 #include "EpetraExt_MatrixMatrix.h"
85 #include "AnasaziBasicEigenproblem.hpp"
86 #include "AnasaziThyraAdapter.hpp"
87 #include "AnasaziBlockKrylovSchurSolMgr.hpp"
88 #include "AnasaziBlockKrylovSchur.hpp"
89 #include "AnasaziStatusTestMaxIters.hpp"
92 #ifdef Teko_ENABLE_Isorropia
93 #include "Isorropia_EpetraProber.hpp"
97 #include "Teko_EpetraHelpers.hpp"
98 #include "Teko_EpetraOperatorWrapper.hpp"
99 #include "Teko_TpetraHelpers.hpp"
100 #include "Teko_TpetraOperatorWrapper.hpp"
103 #include "Thyra_TpetraLinearOp.hpp"
104 #include "Tpetra_CrsMatrix.hpp"
105 #include "Tpetra_Vector.hpp"
106 #include "Thyra_TpetraThyraWrappers.hpp"
107 #include "TpetraExt_MatrixMatrix.hpp"
108 #include "Tpetra_RowMatrixTransposer.hpp"
115 using Teuchos::rcp_dynamic_cast;
117 #ifdef Teko_ENABLE_Isorropia
118 using Isorropia::Epetra::Prober;
121 const Teuchos::RCP<Teuchos::FancyOStream> getOutputStream()
123 Teuchos::RCP<Teuchos::FancyOStream> os =
124 Teuchos::VerboseObjectBase::getDefaultOStream();
132 inline double dist(
int dim,
double * coords,
int row,
int col)
135 for(
int i=0;i<dim;i++)
136 value += std::pow(coords[dim*row+i]-coords[dim*col+i],2.0);
139 return std::sqrt(value);
143 inline double dist(
double * x,
double * y,
double * z,
int stride,
int row,
int col)
146 if(x!=0) value += std::pow(x[stride*row]-x[stride*col],2.0);
147 if(y!=0) value += std::pow(y[stride*row]-y[stride*col],2.0);
148 if(z!=0) value += std::pow(z[stride*row]-z[stride*col],2.0);
151 return std::sqrt(value);
172 RCP<Epetra_CrsMatrix> buildGraphLaplacian(
int dim,
double * coords,
const Epetra_CrsMatrix & stencil)
175 RCP<Epetra_CrsMatrix> gl = rcp(
new Epetra_CrsMatrix(Copy,stencil.RowMap(),stencil.ColMap(),
176 stencil.MaxNumEntries()+1),
true);
179 std::vector<double> rowData(stencil.GlobalMaxNumEntries()+1);
180 std::vector<int> rowInd(stencil.GlobalMaxNumEntries()+1);
183 for(
int j=0;j<gl->NumMyRows();j++) {
184 int row = gl->GRID(j);
185 double diagValue = 0.0;
190 stencil.ExtractGlobalRowCopy(row,stencil.MaxNumEntries(),rowSz,&rowData[0],&rowInd[0]);
193 for(
int i=0;i<rowSz;i++) {
197 double value = rowData[i];
198 if(value==0)
continue;
202 double d = dist(dim,coords,row,col);
204 diagValue += rowData[i];
212 rowData[rowSz] = -diagValue;
217 rowData[diagInd] = -diagValue;
218 rowInd[diagInd] = row;
222 TEUCHOS_TEST_FOR_EXCEPT(gl->InsertGlobalValues(row,rowSz,&rowData[0],&rowInd[0]));
230 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > buildGraphLaplacian(
int dim,ST * coords,
const Tpetra::CrsMatrix<ST,LO,GO,NT> & stencil)
233 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > gl = rcp(
new Tpetra::CrsMatrix<ST,LO,GO,NT>(stencil.getRowMap(),stencil.getColMap(),
234 stencil.getGlobalMaxNumRowEntries()+1));
237 std::vector<ST> rowData(stencil.getGlobalMaxNumRowEntries()+1);
238 std::vector<GO> rowInd(stencil.getGlobalMaxNumRowEntries()+1);
241 for(LO j=0;j< (LO) gl->getNodeNumRows();j++) {
242 GO row = gl->getRowMap()->getGlobalElement(j);
248 stencil.getGlobalRowCopy(row,Teuchos::ArrayView<GO>(rowInd),Teuchos::ArrayView<ST>(rowData),rowSz);
251 for(
size_t i=0;i<rowSz;i++) {
255 ST value = rowData[i];
256 if(value==0)
continue;
260 ST d = dist(dim,coords,row,col);
262 diagValue += rowData[i];
270 rowData[rowSz] = -diagValue;
275 rowData[diagInd] = -diagValue;
276 rowInd[diagInd] = row;
280 gl->replaceGlobalValues(row,Teuchos::ArrayView<GO>(rowInd),Teuchos::ArrayView<ST>(rowData));
310 RCP<Epetra_CrsMatrix> buildGraphLaplacian(
double * x,
double * y,
double * z,
int stride,
const Epetra_CrsMatrix & stencil)
313 RCP<Epetra_CrsMatrix> gl = rcp(
new Epetra_CrsMatrix(Copy,stencil.RowMap(),stencil.ColMap(),
314 stencil.MaxNumEntries()+1),
true);
317 std::vector<double> rowData(stencil.GlobalMaxNumEntries()+1);
318 std::vector<int> rowInd(stencil.GlobalMaxNumEntries()+1);
321 for(
int j=0;j<gl->NumMyRows();j++) {
322 int row = gl->GRID(j);
323 double diagValue = 0.0;
328 stencil.ExtractGlobalRowCopy(row,stencil.MaxNumEntries(),rowSz,&rowData[0],&rowInd[0]);
331 for(
int i=0;i<rowSz;i++) {
335 double value = rowData[i];
336 if(value==0)
continue;
340 double d = dist(x,y,z,stride,row,col);
342 diagValue += rowData[i];
350 rowData[rowSz] = -diagValue;
355 rowData[diagInd] = -diagValue;
356 rowInd[diagInd] = row;
360 TEUCHOS_TEST_FOR_EXCEPT(gl->InsertGlobalValues(row,rowSz,&rowData[0],&rowInd[0]));
368 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > buildGraphLaplacian(ST * x,ST * y,ST * z,GO stride,
const Tpetra::CrsMatrix<ST,LO,GO,NT> & stencil)
371 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > gl = rcp(
new Tpetra::CrsMatrix<ST,LO,GO,NT>(stencil.getRowMap(),stencil.getColMap(),
372 stencil.getGlobalMaxNumRowEntries()+1),
true);
375 std::vector<ST> rowData(stencil.getGlobalMaxNumRowEntries()+1);
376 std::vector<GO> rowInd(stencil.getGlobalMaxNumRowEntries()+1);
379 for(LO j=0;j<(LO) gl->getNodeNumRows();j++) {
380 GO row = gl->getRowMap()->getGlobalElement(j);
386 stencil.getGlobalRowCopy(row,Teuchos::ArrayView<GO>(rowInd),Teuchos::ArrayView<ST>(rowData),rowSz);
389 for(
size_t i=0;i<rowSz;i++) {
393 ST value = rowData[i];
394 if(value==0)
continue;
398 ST d = dist(x,y,z,stride,row,col);
400 diagValue += rowData[i];
408 rowData[rowSz] = -diagValue;
413 rowData[diagInd] = -diagValue;
414 rowInd[diagInd] = row;
418 gl->replaceGlobalValues(row,Teuchos::ArrayView<GO>(rowInd),Teuchos::ArrayView<ST>(rowData));
441 void applyOp(
const LinearOp & A,
const MultiVector & x,MultiVector & y,
double alpha,
double beta)
443 Thyra::apply(*A,Thyra::NOTRANS,*x,y.ptr(),alpha,beta);
461 void applyTransposeOp(
const LinearOp & A,
const MultiVector & x,MultiVector & y,
double alpha,
double beta)
463 Thyra::apply(*A,Thyra::TRANS,*x,y.ptr(),alpha,beta);
468 void update(
double alpha,
const MultiVector & x,
double beta,MultiVector & y)
470 Teuchos::Array<double>
scale;
471 Teuchos::Array<Teuchos::Ptr<const Thyra::MultiVectorBase<double> > > vec;
474 scale.push_back(alpha);
475 vec.push_back(x.ptr());
478 Thyra::linear_combination<double>(scale,vec,beta,y.ptr());
482 BlockedLinearOp getUpperTriBlocks(
const BlockedLinearOp & blo,
bool callEndBlockFill)
488 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
489 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
495 upper->beginBlockFill(rows,rows);
497 for(
int i=0;i<rows;i++) {
501 RCP<const Thyra::LinearOpBase<double> > zed
502 = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
503 upper->setBlock(i,i,zed);
505 for(
int j=i+1;j<rows;j++) {
507 LinearOp uij = blo->getBlock(i,j);
510 if(uij!=Teuchos::null)
511 upper->setBlock(i,j,uij);
515 upper->endBlockFill();
521 BlockedLinearOp getLowerTriBlocks(
const BlockedLinearOp & blo,
bool callEndBlockFill)
527 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
528 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
534 lower->beginBlockFill(rows,rows);
536 for(
int i=0;i<rows;i++) {
540 RCP<const Thyra::LinearOpBase<double> > zed
541 = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
542 lower->setBlock(i,i,zed);
544 for(
int j=0;j<i;j++) {
546 LinearOp uij = blo->getBlock(i,j);
549 if(uij!=Teuchos::null)
550 lower->setBlock(i,j,uij);
554 lower->endBlockFill();
578 BlockedLinearOp zeroBlockedOp(
const BlockedLinearOp & blo)
584 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
585 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
591 zeroOp->beginBlockFill(rows,rows);
593 for(
int i=0;i<rows;i++) {
597 RCP<const Thyra::LinearOpBase<double> > zed
598 = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
599 zeroOp->setBlock(i,i,zed);
606 bool isZeroOp(
const LinearOp op)
609 if(op==Teuchos::null)
return true;
612 LinearOp test = rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<double> >(op);
615 if(test!=Teuchos::null)
return true;
619 Thyra::EOpTransp transp = Thyra::NOTRANS;
620 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
621 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
622 test = rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<double> >(wrapped_op);
623 return test!=Teuchos::null;
634 ModifiableLinearOp getAbsRowSumMatrix(
const LinearOp & op)
636 bool isTpetra =
false;
637 RCP<const Epetra_CrsMatrix> eCrsOp;
638 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
642 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
643 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
646 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
648 eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
650 else if (!tOp.is_null()){
651 tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
655 throw std::logic_error(
"Neither Epetra nor Tpetra");
657 catch (std::exception & e) {
658 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
660 *out <<
"Teko: getAbsRowSumMatrix requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
661 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
663 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
665 *out <<
"*** THROWN EXCEPTION ***\n";
666 *out << e.what() << std::endl;
667 *out <<
"************************\n";
674 const RCP<Epetra_Vector> ptrDiag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
675 Epetra_Vector & diag = *ptrDiag;
679 for(
int i=0;i<eCrsOp->NumMyRows();i++) {
682 eCrsOp->ExtractMyRowView(i,numEntries,values);
685 for(
int j=0;j<numEntries;j++)
686 diag[i] += std::abs(values[j]);
690 return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),
"absRowSum( " + op->getObjectLabel() +
" )");
694 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
695 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
699 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
700 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
701 std::vector<LO> indices(numEntries);
702 std::vector<ST> values(numEntries);
703 Teuchos::ArrayView<const LO> indices_av(indices);
704 Teuchos::ArrayView<const ST> values_av(values);
705 tCrsOp->getLocalRowView(i,indices_av,values_av);
708 for(LO j=0;j<numEntries;j++)
709 diag.sumIntoLocalValue(i,std::abs(values_av[j]));
713 return Teko::TpetraHelpers::thyraDiagOp(ptrDiag,*tCrsOp->getRowMap(),
"absRowSum( " + op->getObjectLabel() +
" ))");
727 ModifiableLinearOp getAbsRowSumInvMatrix(
const LinearOp & op)
731 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
732 if(blocked_op != Teuchos::null){
733 int numRows = blocked_op->productRange()->numBlocks();
734 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == numRows);
735 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_diag = Thyra::defaultBlockedLinearOp<double>();
736 blocked_diag->beginBlockFill(numRows,numRows);
737 for(
int r = 0; r < numRows; ++r){
738 for(
int c = 0; c < numRows; ++c){
740 blocked_diag->setNonconstBlock(r,c,getAbsRowSumInvMatrix(blocked_op->getBlock(r,c)));
742 blocked_diag->setBlock(r,c,Thyra::zero<double>(blocked_op->getBlock(r,c)->range(),blocked_op->getBlock(r,c)->domain()));
745 blocked_diag->endBlockFill();
749 if(Teko::TpetraHelpers::isTpetraLinearOp(op)) {
752 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
755 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
756 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
760 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
761 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
762 std::vector<LO> indices(numEntries);
763 std::vector<ST> values(numEntries);
764 Teuchos::ArrayView<const LO> indices_av(indices);
765 Teuchos::ArrayView<const ST> values_av(values);
766 tCrsOp->getLocalRowView(i,indices_av,values_av);
769 for(LO j=0;j<numEntries;j++)
770 diag.sumIntoLocalValue(i,std::abs(values_av[j]));
773 diag.reciprocal(diag);
776 return Teko::TpetraHelpers::thyraDiagOp(ptrDiag,*tCrsOp->getRowMap(),
"absRowSum( " + op->getObjectLabel() +
" ))");
780 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op,
true);
781 RCP<const Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
784 const RCP<Epetra_Vector> ptrDiag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
785 Epetra_Vector & diag = *ptrDiag;
789 for(
int i=0;i<eCrsOp->NumMyRows();i++) {
792 eCrsOp->ExtractMyRowView(i,numEntries,values);
795 for(
int j=0;j<numEntries;j++)
796 diag[i] += std::abs(values[j]);
798 diag.Reciprocal(diag);
801 return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),
"absRowSum( " + op->getObjectLabel() +
" )");
813 ModifiableLinearOp getLumpedMatrix(
const LinearOp & op)
815 RCP<Thyra::VectorBase<ST> > ones = Thyra::createMember(op->domain());
816 RCP<Thyra::VectorBase<ST> > diag = Thyra::createMember(op->range());
819 Thyra::assign(ones.ptr(),1.0);
823 Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
825 return rcp(
new Thyra::DefaultDiagonalLinearOp<ST>(diag));
836 ModifiableLinearOp getInvLumpedMatrix(
const LinearOp & op)
838 RCP<Thyra::VectorBase<ST> > ones = Thyra::createMember(op->domain());
839 RCP<Thyra::VectorBase<ST> > diag = Thyra::createMember(op->range());
842 Thyra::assign(ones.ptr(),1.0);
845 Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
846 Thyra::reciprocal(*diag,diag.ptr());
848 return rcp(
new Thyra::DefaultDiagonalLinearOp<ST>(diag));
862 const ModifiableLinearOp getDiagonalOp(
const LinearOp & op)
864 bool isTpetra =
false;
865 RCP<const Epetra_CrsMatrix> eCrsOp;
866 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
870 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
871 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
874 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
876 eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
878 else if (!tOp.is_null()){
879 tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
883 throw std::logic_error(
"Neither Epetra nor Tpetra");
885 catch (std::exception & e) {
886 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
888 *out <<
"Teko: getDiagonalOp requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
889 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
891 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
893 *out <<
"*** THROWN EXCEPTION ***\n";
894 *out << e.what() << std::endl;
895 *out <<
"************************\n";
902 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
903 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
906 return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
910 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
911 tCrsOp->getLocalDiagCopy(*diag);
914 return Teko::TpetraHelpers::thyraDiagOp(diag,*tCrsOp->getRowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
919 const MultiVector getDiagonal(
const LinearOp & op)
921 bool isTpetra =
false;
922 RCP<const Epetra_CrsMatrix> eCrsOp;
923 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
927 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
928 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
931 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
933 eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
935 else if (!tOp.is_null()){
936 tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
940 throw std::logic_error(
"Neither Epetra nor Tpetra");
942 catch (std::exception & e) {
943 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
945 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
946 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
950 *out <<
"Teko: getDiagonal requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
951 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
953 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
955 *out <<
"*** THROWN EXCEPTION ***\n";
956 *out << e.what() << std::endl;
957 *out <<
"************************\n";
964 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
965 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
967 return Thyra::create_Vector(diag,Thyra::create_VectorSpace(Teuchos::rcpFromRef(eCrsOp->RowMap())));
971 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
972 tCrsOp->getLocalDiagCopy(*diag);
975 return Thyra::createVector<ST,LO,GO,NT>(diag,Thyra::createVectorSpace<ST,LO,GO,NT>(tCrsOp->getRowMap()));
980 const MultiVector getDiagonal(
const Teko::LinearOp & A,
const DiagonalType & dt)
982 LinearOp diagOp = Teko::getDiagonalOp(A,dt);
984 Teuchos::RCP<const Thyra::MultiVectorBase<double> > v =
985 Teuchos::rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<double> >(diagOp)->getDiag();
986 return Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(v);
1000 const ModifiableLinearOp getInvDiagonalOp(
const LinearOp & op)
1003 auto diagonal_op = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<double>>(op);
1004 if(diagonal_op != Teuchos::null){
1005 auto diag = diagonal_op->getDiag();
1006 auto inv_diag = diag->clone_v();
1007 Thyra::reciprocal(*diag,inv_diag.ptr());
1008 return rcp(
new Thyra::DefaultDiagonalLinearOp<double>(inv_diag));
1012 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
1013 if(blocked_op != Teuchos::null){
1014 int numRows = blocked_op->productRange()->numBlocks();
1015 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == numRows);
1016 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_diag = Thyra::defaultBlockedLinearOp<double>();
1017 blocked_diag->beginBlockFill(numRows,numRows);
1018 for(
int r = 0; r < numRows; ++r){
1019 for(
int c = 0; c < numRows; ++c){
1021 blocked_diag->setNonconstBlock(r,c,getInvDiagonalOp(blocked_op->getBlock(r,c)));
1023 blocked_diag->setBlock(r,c,Thyra::zero<double>(blocked_op->getBlock(r,c)->range(),blocked_op->getBlock(r,c)->domain()));
1026 blocked_diag->endBlockFill();
1027 return blocked_diag;
1030 if (Teko::TpetraHelpers::isTpetraLinearOp(op)){
1032 bool transp =
false;
1033 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
1036 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
1037 diag->scale(scalar);
1038 tCrsOp->getLocalDiagCopy(*diag);
1039 diag->reciprocal(*diag);
1042 return Teko::TpetraHelpers::thyraDiagOp(diag,*tCrsOp->getRowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
1046 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op,
true);
1047 RCP<const Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
1050 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
1051 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
1052 diag->Reciprocal(*diag);
1055 return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
1071 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opm,
const LinearOp & opr)
1076 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1077 bool isBlockedM = isPhysicallyBlockedLinearOp(opm);
1078 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1081 if((isBlockedL && isBlockedM && isBlockedR)){
1083 double scalarl = 0.0;
1084 bool transpl =
false;
1085 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1086 double scalarm = 0.0;
1087 bool transpm =
false;
1088 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opm = getPhysicallyBlockedLinearOp(opm,&scalarm,&transpm);
1089 double scalarr = 0.0;
1090 bool transpr =
false;
1091 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1092 double scalar = scalarl*scalarm*scalarr;
1094 int numRows = blocked_opl->productRange()->numBlocks();
1095 int numCols = blocked_opr->productDomain()->numBlocks();
1096 int numMiddle = blocked_opm->productRange()->numBlocks();
1099 TEUCHOS_ASSERT(blocked_opm->productDomain()->numBlocks() == numMiddle);
1100 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1101 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1103 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1104 blocked_product->beginBlockFill(numRows,numCols);
1105 for(
int r = 0; r < numRows; ++r){
1106 for(
int c = 0; c < numCols; ++c){
1107 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opm->getBlock(0,0),blocked_opr->getBlock(0,c));
1108 for(
int m = 1; m < numMiddle; ++m){
1109 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opm->getBlock(m,m),blocked_opr->getBlock(m,c));
1110 product_rc = explicitAdd(product_rc,product_m);
1112 blocked_product->setBlock(r,c,product_rc);
1115 blocked_product->endBlockFill();
1116 return Thyra::scale<double>(scalar,blocked_product.getConst());
1120 if(isBlockedL && !isBlockedM && isBlockedR){
1121 double scalarl = 0.0;
1122 bool transpl =
false;
1123 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1124 double scalarr = 0.0;
1125 bool transpr =
false;
1126 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1127 double scalar = scalarl*scalarr;
1129 int numRows = blocked_opl->productRange()->numBlocks();
1130 int numCols = blocked_opr->productDomain()->numBlocks();
1134 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1135 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1137 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1138 blocked_product->beginBlockFill(numRows,numCols);
1139 for(
int r = 0; r < numRows; ++r){
1140 for(
int c = 0; c < numCols; ++c){
1141 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),opm,blocked_opr->getBlock(0,c));
1142 blocked_product->setBlock(r,c,product_rc);
1145 blocked_product->endBlockFill();
1146 return Thyra::scale<double>(scalar,blocked_product.getConst());
1150 if(!isBlockedL && !isBlockedM && isBlockedR){
1151 double scalarr = 0.0;
1152 bool transpr =
false;
1153 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1154 double scalar = scalarr;
1157 int numCols = blocked_opr->productDomain()->numBlocks();
1161 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1163 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1164 blocked_product->beginBlockFill(numRows,numCols);
1165 for(
int c = 0; c < numCols; ++c){
1166 LinearOp product_c = explicitMultiply(opl,opm,blocked_opr->getBlock(0,c));
1167 blocked_product->setBlock(0,c,product_c);
1169 blocked_product->endBlockFill();
1170 return Thyra::scale<double>(scalar,blocked_product.getConst());
1175 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1176 bool isTpetram = Teko::TpetraHelpers::isTpetraLinearOp(opm);
1177 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1179 if(isTpetral && isTpetram && isTpetrar){
1183 bool transpl =
false;
1184 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1186 bool transpm =
false;
1187 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpm = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarm, &transpm);
1189 bool transpr =
false;
1190 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1193 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1194 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1197 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1198 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1199 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1200 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1201 explicitCrsOp->resumeFill();
1202 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1203 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1204 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1207 }
else if (isTpetral && !isTpetram && isTpetrar){
1211 bool transpl =
false;
1212 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1214 bool transpr =
false;
1215 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1217 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1220 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opm);
1221 if(dOpm != Teuchos::null){
1222 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1223 diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1226 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opm) != Teuchos::null){
1227 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpl->getDomainMap()));
1230 TEUCHOS_ASSERT(
false);
1232 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::importAndFillCompleteCrsMatrix<Tpetra::CrsMatrix<ST,LO,GO,NT> >(tCrsOpl, Tpetra::Import<LO,GO,NT>(tCrsOpl->getRowMap(),tCrsOpl->getRowMap()));
1235 tCrsOplm->rightScale(*diagPtr);
1238 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1239 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1242 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1243 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1244 explicitCrsOp->resumeFill();
1245 explicitCrsOp->scale(scalarl*scalarr);
1246 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1247 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1253 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1256 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1257 Thyra::epetraExtDiagScaledMatProdTransformer();
1260 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1261 prodTrans->transform(*implicitOp,explicitOp.ptr());
1262 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1263 " * " + opm->getObjectLabel() +
1264 " * " + opr->getObjectLabel() +
" )");
1285 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opm,
const LinearOp & opr,
1286 const ModifiableLinearOp & destOp)
1288 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1289 bool isTpetram = Teko::TpetraHelpers::isTpetraLinearOp(opm);
1290 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1292 if(isTpetral && isTpetram && isTpetrar){
1296 bool transpl =
false;
1297 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1299 bool transpm =
false;
1300 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpm = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarm, &transpm);
1302 bool transpr =
false;
1303 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1306 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1307 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1310 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1311 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1312 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1313 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1314 explicitCrsOp->resumeFill();
1315 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1316 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1317 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1320 }
else if (isTpetral && !isTpetram && isTpetrar){
1324 bool transpl =
false;
1325 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1327 bool transpr =
false;
1328 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1331 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opm,
true);
1332 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1333 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1334 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::importAndFillCompleteCrsMatrix<Tpetra::CrsMatrix<ST,LO,GO,NT> >(tCrsOpl, Tpetra::Import<LO,GO,NT>(tCrsOpl->getRowMap(),tCrsOpl->getRowMap()));
1337 tCrsOplm->rightScale(*diagPtr);
1340 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1341 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1344 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1345 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1346 explicitCrsOp->resumeFill();
1347 explicitCrsOp->scale(scalarl*scalarr);
1348 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1349 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1355 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1358 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1359 Thyra::epetraExtDiagScaledMatProdTransformer();
1362 ModifiableLinearOp explicitOp;
1365 if(destOp==Teuchos::null)
1366 explicitOp = prodTrans->createOutputOp();
1368 explicitOp = destOp;
1371 prodTrans->transform(*implicitOp,explicitOp.ptr());
1374 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1375 " * " + opm->getObjectLabel() +
1376 " * " + opr->getObjectLabel() +
" )");
1393 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr)
1398 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1399 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1402 if((isBlockedL && isBlockedR)){
1403 double scalarl = 0.0;
1404 bool transpl =
false;
1405 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1406 double scalarr = 0.0;
1407 bool transpr =
false;
1408 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1409 double scalar = scalarl*scalarr;
1411 int numRows = blocked_opl->productRange()->numBlocks();
1412 int numCols = blocked_opr->productDomain()->numBlocks();
1413 int numMiddle = blocked_opl->productDomain()->numBlocks();
1415 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1417 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1418 blocked_product->beginBlockFill(numRows,numCols);
1419 for(
int r = 0; r < numRows; ++r){
1420 for(
int c = 0; c < numCols; ++c){
1421 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1422 for(
int m = 1; m < numMiddle; ++m){
1423 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1424 product_rc = explicitAdd(product_rc,product_m);
1426 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1429 blocked_product->endBlockFill();
1430 return blocked_product;
1434 if((isBlockedL && !isBlockedR)){
1435 double scalarl = 0.0;
1436 bool transpl =
false;
1437 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1438 double scalar = scalarl;
1440 int numRows = blocked_opl->productRange()->numBlocks();
1444 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1446 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1447 blocked_product->beginBlockFill(numRows,numCols);
1448 for(
int r = 0; r < numRows; ++r){
1449 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1450 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1452 blocked_product->endBlockFill();
1453 return blocked_product;
1457 if((!isBlockedL && isBlockedR)){
1458 double scalarr = 0.0;
1459 bool transpr =
false;
1460 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1461 double scalar = scalarr;
1464 int numCols = blocked_opr->productDomain()->numBlocks();
1467 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1469 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1470 blocked_product->beginBlockFill(numRows,numCols);
1471 for(
int c = 0; c < numCols; ++c){
1472 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1473 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1475 blocked_product->endBlockFill();
1476 return blocked_product;
1479 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1480 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1482 if(isTpetral && isTpetrar){
1485 bool transpl =
false;
1486 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1488 bool transpr =
false;
1489 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1492 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1493 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1496 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1497 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1498 explicitCrsOp->resumeFill();
1499 explicitCrsOp->scale(scalarl*scalarr);
1500 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1501 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1504 }
else if (isTpetral && !isTpetrar){
1508 bool transpl =
false;
1509 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1512 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opr,
true);
1513 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1514 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1515 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::importAndFillCompleteCrsMatrix<Tpetra::CrsMatrix<ST,LO,GO,NT> >(tCrsOpl, Tpetra::Import<LO,GO,NT>(tCrsOpl->getRowMap(),tCrsOpl->getRowMap()));
1517 explicitCrsOp->rightScale(*diagPtr);
1518 explicitCrsOp->resumeFill();
1519 explicitCrsOp->scale(scalarl);
1520 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1522 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1524 }
else if (!isTpetral && isTpetrar){
1528 bool transpr =
false;
1529 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1531 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1534 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opl);
1535 if(dOpl != Teuchos::null){
1536 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1537 diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1540 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opl) != Teuchos::null){
1541 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpr->getRangeMap()));
1544 TEUCHOS_ASSERT(
false);
1546 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::importAndFillCompleteCrsMatrix<Tpetra::CrsMatrix<ST,LO,GO,NT> >(tCrsOpr, Tpetra::Import<LO,GO,NT>(tCrsOpr->getRowMap(),tCrsOpr->getRowMap()));
1548 explicitCrsOp->leftScale(*diagPtr);
1549 explicitCrsOp->resumeFill();
1550 explicitCrsOp->scale(scalarr);
1551 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1553 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1558 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1561 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1562 = Thyra::epetraExtDiagScalingTransformer();
1566 if(not prodTrans->isCompatible(*implicitOp))
1567 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1570 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1571 prodTrans->transform(*implicitOp,explicitOp.ptr());
1572 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1573 " * " + opr->getObjectLabel() +
" )");
1592 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr,
1593 const ModifiableLinearOp & destOp)
1598 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1599 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1602 if((isBlockedL && isBlockedR)){
1603 double scalarl = 0.0;
1604 bool transpl =
false;
1605 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1606 double scalarr = 0.0;
1607 bool transpr =
false;
1608 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1609 double scalar = scalarl*scalarr;
1611 int numRows = blocked_opl->productRange()->numBlocks();
1612 int numCols = blocked_opr->productDomain()->numBlocks();
1613 int numMiddle = blocked_opl->productDomain()->numBlocks();
1615 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1617 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1618 blocked_product->beginBlockFill(numRows,numCols);
1619 for(
int r = 0; r < numRows; ++r){
1620 for(
int c = 0; c < numCols; ++c){
1622 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1623 for(
int m = 1; m < numMiddle; ++m){
1624 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1625 product_rc = explicitAdd(product_rc,product_m);
1627 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1630 blocked_product->endBlockFill();
1631 return blocked_product;
1635 if((isBlockedL && !isBlockedR)){
1636 double scalarl = 0.0;
1637 bool transpl =
false;
1638 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1639 double scalar = scalarl;
1641 int numRows = blocked_opl->productRange()->numBlocks();
1645 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1647 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1648 blocked_product->beginBlockFill(numRows,numCols);
1649 for(
int r = 0; r < numRows; ++r){
1650 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1651 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1653 blocked_product->endBlockFill();
1654 return blocked_product;
1658 if((!isBlockedL && isBlockedR)){
1659 double scalarr = 0.0;
1660 bool transpr =
false;
1661 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1662 double scalar = scalarr;
1665 int numCols = blocked_opr->productDomain()->numBlocks();
1668 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1670 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1671 blocked_product->beginBlockFill(numRows,numCols);
1672 for(
int c = 0; c < numCols; ++c){
1673 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1674 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1676 blocked_product->endBlockFill();
1677 return blocked_product;
1680 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1681 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1683 if(isTpetral && isTpetrar){
1687 bool transpl =
false;
1688 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1690 bool transpr =
false;
1691 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1694 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1695 if(destOp!=Teuchos::null)
1696 explicitOp = destOp;
1698 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1699 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1702 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1703 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1704 explicitCrsOp->resumeFill();
1705 explicitCrsOp->scale(scalarl*scalarr);
1706 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1707 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1710 }
else if (isTpetral && !isTpetrar){
1714 bool transpl =
false;
1715 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1718 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opr);
1719 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1720 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1723 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::importAndFillCompleteCrsMatrix<Tpetra::CrsMatrix<ST,LO,GO,NT> >(tCrsOpl, Tpetra::Import<LO,GO,NT>(tCrsOpl->getRowMap(),tCrsOpl->getRowMap()));
1724 explicitCrsOp->rightScale(*diagPtr);
1725 explicitCrsOp->resumeFill();
1726 explicitCrsOp->scale(scalarl);
1727 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1728 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1730 }
else if (!isTpetral && isTpetrar){
1734 bool transpr =
false;
1735 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1738 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opl,
true);
1739 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1740 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1743 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::importAndFillCompleteCrsMatrix<Tpetra::CrsMatrix<ST,LO,GO,NT> >(tCrsOpr, Tpetra::Import<LO,GO,NT>(tCrsOpr->getRowMap(),tCrsOpr->getRowMap()));
1744 explicitCrsOp->leftScale(*diagPtr);
1745 explicitCrsOp->resumeFill();
1746 explicitCrsOp->scale(scalarr);
1747 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1748 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1753 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1757 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1758 = Thyra::epetraExtDiagScalingTransformer();
1762 if(not prodTrans->isCompatible(*implicitOp))
1763 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1766 ModifiableLinearOp explicitOp;
1769 if(destOp==Teuchos::null)
1770 explicitOp = prodTrans->createOutputOp();
1772 explicitOp = destOp;
1775 prodTrans->transform(*implicitOp,explicitOp.ptr());
1778 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1779 " * " + opr->getObjectLabel() +
" )");
1795 const LinearOp explicitAdd(
const LinearOp & opl_in,
const LinearOp & opr_in)
1798 if(isPhysicallyBlockedLinearOp(opl_in) && isPhysicallyBlockedLinearOp(opr_in)){
1799 double scalarl = 0.0;
1800 bool transpl =
false;
1801 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl_in, &scalarl, &transpl);
1803 double scalarr = 0.0;
1804 bool transpr =
false;
1805 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr_in, &scalarr, &transpr);
1807 int numRows = blocked_opl->productRange()->numBlocks();
1808 int numCols = blocked_opl->productDomain()->numBlocks();
1809 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1810 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1812 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1813 blocked_sum->beginBlockFill(numRows,numCols);
1814 for(
int r = 0; r < numRows; ++r)
1815 for(
int c = 0; c < numCols; ++c)
1816 blocked_sum->setBlock(r,c,explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c))));
1817 blocked_sum->endBlockFill();
1822 LinearOp opl = opl_in;
1823 LinearOp opr = opr_in;
1824 if(isPhysicallyBlockedLinearOp(opl_in)){
1825 double scalarl = 0.0;
1826 bool transpl =
false;
1827 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl_in, &scalarl, &transpl);
1828 TEUCHOS_ASSERT(blocked_opl->productRange()->numBlocks() == 1);
1829 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == 1);
1830 opl = Thyra::scale(scalarl,blocked_opl->getBlock(0,0));
1832 if(isPhysicallyBlockedLinearOp(opr_in)){
1833 double scalarr = 0.0;
1834 bool transpr =
false;
1835 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr_in, &scalarr, &transpr);
1836 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == 1);
1837 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == 1);
1838 opr = Thyra::scale(scalarr,blocked_opr->getBlock(0,0));
1841 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1842 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1850 bool transp =
false;
1851 auto crs_op = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalar, &transp);
1852 auto zero_crs = Tpetra::createCrsMatrix<ST,LO,GO,NT>(crs_op->getRowMap());
1853 zero_crs->fillComplete();
1854 opl = Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(crs_op->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(crs_op->getDomainMap()),zero_crs);
1857 return opr->clone();
1862 bool transp =
false;
1863 auto crs_op = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalar, &transp);
1864 auto zero_crs = Tpetra::createCrsMatrix<ST,LO,GO,NT>(crs_op->getRowMap());
1865 zero_crs->fillComplete();
1866 opr = Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(crs_op->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(crs_op->getDomainMap()),zero_crs);
1869 return opl->clone();
1872 if(isTpetral && isTpetrar){
1876 bool transpl =
false;
1877 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1879 bool transpr =
false;
1880 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1883 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1884 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1887 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1888 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1893 const LinearOp implicitOp = Thyra::add(opl,opr);
1896 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1897 Thyra::epetraExtAddTransformer();
1900 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1901 prodTrans->transform(*implicitOp,explicitOp.ptr());
1902 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1903 " + " + opr->getObjectLabel() +
" )");
1921 const ModifiableLinearOp explicitAdd(
const LinearOp & opl,
const LinearOp & opr,
1922 const ModifiableLinearOp & destOp)
1925 if(isPhysicallyBlockedLinearOp(opl)){
1926 TEUCHOS_ASSERT(isPhysicallyBlockedLinearOp(opr));
1928 double scalarl = 0.0;
1929 bool transpl =
false;
1930 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl, &scalarl, &transpl);
1932 double scalarr = 0.0;
1933 bool transpr =
false;
1934 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr, &scalarr, &transpr);
1936 int numRows = blocked_opl->productRange()->numBlocks();
1937 int numCols = blocked_opl->productDomain()->numBlocks();
1938 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1939 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1941 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1942 blocked_sum->beginBlockFill(numRows,numCols);
1943 for(
int r = 0; r < numRows; ++r)
1944 for(
int c = 0; c < numCols; ++c)
1945 blocked_sum->setBlock(r,c,explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c))));
1946 blocked_sum->endBlockFill();
1950 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1951 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1953 if(isTpetral && isTpetrar){
1957 bool transpl =
false;
1958 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1960 bool transpr =
false;
1961 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1964 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1965 if(destOp!=Teuchos::null)
1966 explicitOp = destOp;
1968 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1969 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1972 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1973 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1979 const LinearOp implicitOp = Thyra::add(opl,opr);
1982 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1983 Thyra::epetraExtAddTransformer();
1986 RCP<Thyra::LinearOpBase<double> > explicitOp;
1987 if(destOp!=Teuchos::null)
1988 explicitOp = destOp;
1990 explicitOp = prodTrans->createOutputOp();
1993 prodTrans->transform(*implicitOp,explicitOp.ptr());
1994 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1995 " + " + opr->getObjectLabel() +
" )");
2005 const ModifiableLinearOp explicitSum(
const LinearOp & op,
2006 const ModifiableLinearOp & destOp)
2009 const RCP<const Epetra_CrsMatrix> epetraOp =
2010 rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*op),
true);
2012 if(destOp==Teuchos::null) {
2013 Teuchos::RCP<Epetra_Operator> epetraDest = Teuchos::rcp(
new Epetra_CrsMatrix(*epetraOp));
2015 return Thyra::nonconstEpetraLinearOp(epetraDest);
2018 const RCP<Epetra_CrsMatrix> epetraDest =
2019 rcp_dynamic_cast<Epetra_CrsMatrix>(get_Epetra_Operator(*destOp),
true);
2021 EpetraExt::MatrixMatrix::Add(*epetraOp,
false,1.0,*epetraDest,1.0);
2026 const LinearOp explicitTranspose(
const LinearOp & op)
2028 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2030 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op,
true);
2031 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
2033 Tpetra::RowMatrixTransposer<ST,LO,GO,NT> transposer(tCrsOp);
2034 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > transOp = transposer.createTranspose();
2036 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getDomainMap()),transOp);
2040 RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2041 TEUCHOS_TEST_FOR_EXCEPTION(eOp==Teuchos::null,std::logic_error,
2042 "Teko::explicitTranspose Not an Epetra_Operator");
2043 RCP<const Epetra_RowMatrix> eRowMatrixOp
2044 = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(eOp);
2045 TEUCHOS_TEST_FOR_EXCEPTION(eRowMatrixOp==Teuchos::null,std::logic_error,
2046 "Teko::explicitTranspose Not an Epetra_RowMatrix");
2049 EpetraExt::RowMatrix_Transpose tranposeOp;
2050 Epetra_RowMatrix & eMat = tranposeOp(const_cast<Epetra_RowMatrix &>(*eRowMatrixOp));
2054 Teuchos::RCP<Epetra_CrsMatrix> crsMat
2055 = Teuchos::rcp(
new Epetra_CrsMatrix(dynamic_cast<Epetra_CrsMatrix &>(eMat)));
2057 return Thyra::epetraLinearOp(crsMat);
2061 double frobeniusNorm(
const LinearOp & op_in)
2064 double scalar = 1.0;
2067 if(isPhysicallyBlockedLinearOp(op_in)){
2068 bool transp =
false;
2069 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = getPhysicallyBlockedLinearOp(op_in,&scalar,&transp);
2070 TEUCHOS_ASSERT(blocked_op->productRange()->numBlocks() == 1);
2071 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == 1);
2072 op = blocked_op->getBlock(0,0);
2076 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2077 const RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
2078 const RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > crsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
2079 return crsOp->getFrobeniusNorm();
2081 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2082 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(epOp,
true);
2083 return crsOp->NormFrobenius();
2087 double oneNorm(
const LinearOp & op)
2089 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2090 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"One norm not currently implemented for Tpetra matrices");
2093 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2094 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(epOp,
true);
2095 return crsOp->NormOne();
2099 double infNorm(
const LinearOp & op)
2101 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2103 bool transp =
false;
2104 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
2107 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
2108 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
2111 diag.putScalar(0.0);
2112 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
2113 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
2114 std::vector<LO> indices(numEntries);
2115 std::vector<ST> values(numEntries);
2116 Teuchos::ArrayView<const LO> indices_av(indices);
2117 Teuchos::ArrayView<const ST> values_av(values);
2118 tCrsOp->getLocalRowView(i,indices_av,values_av);
2121 for(LO j=0;j<numEntries;j++)
2122 diag.sumIntoLocalValue(i,std::abs(values_av[j]));
2124 return diag.normInf()*scalar;
2127 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2128 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(epOp,
true);
2129 return crsOp->NormInf();
2133 const LinearOp buildDiagonal(
const MultiVector & src,
const std::string & lbl)
2135 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(src->range());
2136 Thyra::copy(*src->col(0),dst.ptr());
2138 return Thyra::diagonal<double>(dst,lbl);
2141 const LinearOp buildInvDiagonal(
const MultiVector & src,
const std::string & lbl)
2143 const RCP<const Thyra::VectorBase<double> > srcV = src->col(0);
2144 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(srcV->range());
2145 Thyra::reciprocal<double>(*srcV,dst.ptr());
2147 return Thyra::diagonal<double>(dst,lbl);
2151 BlockedMultiVector buildBlockedMultiVector(
const std::vector<MultiVector> & mvv)
2153 Teuchos::Array<MultiVector> mvA;
2154 Teuchos::Array<VectorSpace> vsA;
2157 std::vector<MultiVector>::const_iterator itr;
2158 for(itr=mvv.begin();itr!=mvv.end();++itr) {
2159 mvA.push_back(*itr);
2160 vsA.push_back((*itr)->range());
2164 const RCP<const Thyra::DefaultProductVectorSpace<double> > vs
2165 = Thyra::productVectorSpace<double>(vsA);
2167 return Thyra::defaultProductMultiVector<double>(vs,mvA);
2180 Teuchos::RCP<Thyra::VectorBase<double> > indicatorVector(
2181 const std::vector<int> & indices,
2182 const VectorSpace & vs,
2183 double onValue,
double offValue)
2189 RCP<Thyra::VectorBase<double> > v = Thyra::createMember<double>(vs);
2190 Thyra::put_scalar<double>(offValue,v.ptr());
2193 for(std::size_t i=0;i<indices.size();i++)
2194 Thyra::set_ele<double>(indices[i],onValue,v.ptr());
2223 double computeSpectralRad(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2224 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2226 typedef Thyra::LinearOpBase<double> OP;
2227 typedef Thyra::MultiVectorBase<double> MV;
2229 int startVectors = 1;
2232 const RCP<MV> ivec = Thyra::createMember(A->domain());
2233 Thyra::randomize(-1.0,1.0,ivec.ptr());
2235 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2236 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2238 eigProb->setHermitian(isHermitian);
2241 if(not eigProb->setProblem()) {
2243 return Teuchos::ScalarTraits<double>::nan();
2247 std::string which(
"LM");
2251 Teuchos::ParameterList MyPL;
2252 MyPL.set(
"Verbosity", verbosity );
2253 MyPL.set(
"Which", which );
2254 MyPL.set(
"Block Size", startVectors );
2255 MyPL.set(
"Num Blocks", numBlocks );
2256 MyPL.set(
"Maximum Restarts", restart );
2257 MyPL.set(
"Convergence Tolerance", tol );
2265 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2268 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2270 if(solverreturn==Anasazi::Unconverged) {
2271 double real = MyBlockKrylovSchur.getRitzValues().begin()->realpart;
2272 double comp = MyBlockKrylovSchur.getRitzValues().begin()->imagpart;
2274 return -std::abs(std::sqrt(real*real+comp*comp));
2280 double real = eigProb->getSolution().Evals.begin()->realpart;
2281 double comp = eigProb->getSolution().Evals.begin()->imagpart;
2283 return std::abs(std::sqrt(real*real+comp*comp));
2313 double computeSmallestMagEig(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2314 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2316 typedef Thyra::LinearOpBase<double> OP;
2317 typedef Thyra::MultiVectorBase<double> MV;
2319 int startVectors = 1;
2322 const RCP<MV> ivec = Thyra::createMember(A->domain());
2323 Thyra::randomize(-1.0,1.0,ivec.ptr());
2325 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2326 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2328 eigProb->setHermitian(isHermitian);
2331 if(not eigProb->setProblem()) {
2333 return Teuchos::ScalarTraits<double>::nan();
2337 std::string which(
"SM");
2340 Teuchos::ParameterList MyPL;
2341 MyPL.set(
"Verbosity", verbosity );
2342 MyPL.set(
"Which", which );
2343 MyPL.set(
"Block Size", startVectors );
2344 MyPL.set(
"Num Blocks", numBlocks );
2345 MyPL.set(
"Maximum Restarts", restart );
2346 MyPL.set(
"Convergence Tolerance", tol );
2354 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2357 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2359 if(solverreturn==Anasazi::Unconverged) {
2361 return -std::abs(MyBlockKrylovSchur.getRitzValues().begin()->realpart);
2365 return std::abs(eigProb->getSolution().Evals.begin()->realpart);
2377 ModifiableLinearOp getDiagonalOp(
const Teko::LinearOp & A,
const DiagonalType & dt)
2381 return getDiagonalOp(A);
2383 return getLumpedMatrix(A);
2385 return getAbsRowSumMatrix(A);
2388 TEUCHOS_TEST_FOR_EXCEPT(
true);
2391 return Teuchos::null;
2402 ModifiableLinearOp getInvDiagonalOp(
const Teko::LinearOp & A,
const Teko::DiagonalType & dt)
2406 return getInvDiagonalOp(A);
2408 return getInvLumpedMatrix(A);
2410 return getAbsRowSumInvMatrix(A);
2413 TEUCHOS_TEST_FOR_EXCEPT(
true);
2416 return Teuchos::null;
2425 std::string getDiagonalName(
const DiagonalType & dt)
2453 if(name==
"Diagonal")
2457 if(name==
"AbsRowSum")
2465 LinearOp probe(Teuchos::RCP<const Epetra_CrsGraph> &G,
const LinearOp & Op){
2466 #ifdef Teko_ENABLE_Isorropia
2467 Teuchos::ParameterList probeList;
2468 Prober prober(G,probeList,
true);
2469 Teuchos::RCP<Epetra_CrsMatrix> Mat=rcp(
new Epetra_CrsMatrix(Copy,*G));
2471 prober.probe(Mwrap,*Mat);
2472 return Thyra::epetraLinearOp(Mat);
2474 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::runtime_error,
"Probe requires Isorropia");
2478 double norm_1(
const MultiVector & v,std::size_t col)
2480 Teuchos::Array<double> n(v->domain()->dim());
2481 Thyra::norms_1<double>(*v,n);
2486 double norm_2(
const MultiVector & v,std::size_t col)
2488 Teuchos::Array<double> n(v->domain()->dim());
2489 Thyra::norms_2<double>(*v,n);
2494 void putScalar(
const ModifiableLinearOp & op,
double scalar)
2498 RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2501 RCP<Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
2503 eCrsOp->PutScalar(scalar);
2505 catch (std::exception & e) {
2506 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
2508 *out <<
"Teko: putScalar requires an Epetra_CrsMatrix\n";
2509 *out <<
" Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
2511 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
2513 *out <<
"*** THROWN EXCEPTION ***\n";
2514 *out << e.what() << std::endl;
2515 *out <<
"************************\n";
2521 void clipLower(MultiVector & v,
double lowerBound)
2524 using Teuchos::rcp_dynamic_cast;
2530 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2531 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2532 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2534 Teuchos::ArrayRCP<double> values;
2536 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2537 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2538 if(values[j]<lowerBound)
2539 values[j] = lowerBound;
2544 void clipUpper(MultiVector & v,
double upperBound)
2547 using Teuchos::rcp_dynamic_cast;
2552 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2553 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2554 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2556 Teuchos::ArrayRCP<double> values;
2558 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2559 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2560 if(values[j]>upperBound)
2561 values[j] = upperBound;
2566 void replaceValue(MultiVector & v,
double currentValue,
double newValue)
2569 using Teuchos::rcp_dynamic_cast;
2574 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2575 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2576 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2578 Teuchos::ArrayRCP<double> values;
2580 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2581 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2582 if(values[j]==currentValue)
2583 values[j] = newValue;
2588 void columnAverages(
const MultiVector & v,std::vector<double> & averages)
2590 averages.resize(v->domain()->dim());
2593 Thyra::sums<double>(*v,averages);
2596 Thyra::Ordinal rows = v->range()->dim();
2597 for(std::size_t i=0;i<averages.size();i++)
2598 averages[i] = averages[i]/rows;
2601 double average(
const MultiVector & v)
2603 Thyra::Ordinal rows = v->range()->dim();
2604 Thyra::Ordinal cols = v->domain()->dim();
2606 std::vector<double> averages;
2607 columnAverages(v,averages);
2610 for(std::size_t i=0;i<averages.size();i++)
2611 sum += averages[i] * rows;
2613 return sum/(rows*cols);
2616 bool isPhysicallyBlockedLinearOp(
const LinearOp & op)
2619 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2620 if (!pblo.is_null())
2625 Thyra::EOpTransp transp = Thyra::NOTRANS;
2626 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2627 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
2628 pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op);
2629 if (!pblo.is_null())
2635 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > getPhysicallyBlockedLinearOp(
const LinearOp & op, ST *scalar,
bool *transp)
2638 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2639 if(!pblo.is_null()){
2646 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2647 Thyra::EOpTransp eTransp = Thyra::NOTRANS;
2648 Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
2649 pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op,
true);
2650 if(!pblo.is_null()){
2652 if(eTransp == Thyra::NOTRANS)
2657 return Teuchos::null;