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;
Specifies that a block diagonal approximation is to be used.
Specifies that just the diagonal is used.
int blockRowCount(const BlockedLinearOp &blo)
Get the row count in a block linear operator.
Specifies that row sum is used to form a diagonal.
void scale(const double alpha, MultiVector &x)
Scale a multivector by a constant.
Implements the Epetra_Operator interface with a Thyra LinearOperator. This enables the use of absrtac...
For user convenience, if Teko recieves this value, exceptions will be thrown.
DiagonalType
Type describing the type of diagonal to construct.
int blockColCount(const BlockedLinearOp &blo)
Get the column count in a block linear operator.
BlockedLinearOp createBlockedOp()
Build a new blocked linear operator.
Specifies that the diagonal entry is .