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(opm, &scalarm, &transpm);
1302 bool transpr =
false;
1303 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1306 auto tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(destOp);
1307 if(tExplicitOp.is_null())
1308 tExplicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1311 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1312 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1313 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1314 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1315 explicitCrsOp->resumeFill();
1316 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1317 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1318 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1321 }
else if (isTpetral && !isTpetram && isTpetrar){
1325 bool transpl =
false;
1326 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1328 bool transpr =
false;
1329 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1332 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opm,
true);
1333 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1334 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1335 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()));
1338 tCrsOplm->rightScale(*diagPtr);
1341 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1342 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1345 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1346 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1347 explicitCrsOp->resumeFill();
1348 explicitCrsOp->scale(scalarl*scalarr);
1349 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1350 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1356 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1359 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1360 Thyra::epetraExtDiagScaledMatProdTransformer();
1363 ModifiableLinearOp explicitOp;
1366 if(destOp==Teuchos::null)
1367 explicitOp = prodTrans->createOutputOp();
1369 explicitOp = destOp;
1372 prodTrans->transform(*implicitOp,explicitOp.ptr());
1375 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1376 " * " + opm->getObjectLabel() +
1377 " * " + opr->getObjectLabel() +
" )");
1394 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr)
1399 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1400 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1403 if((isBlockedL && isBlockedR)){
1404 double scalarl = 0.0;
1405 bool transpl =
false;
1406 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1407 double scalarr = 0.0;
1408 bool transpr =
false;
1409 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1410 double scalar = scalarl*scalarr;
1412 int numRows = blocked_opl->productRange()->numBlocks();
1413 int numCols = blocked_opr->productDomain()->numBlocks();
1414 int numMiddle = blocked_opl->productDomain()->numBlocks();
1416 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1418 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1419 blocked_product->beginBlockFill(numRows,numCols);
1420 for(
int r = 0; r < numRows; ++r){
1421 for(
int c = 0; c < numCols; ++c){
1422 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1423 for(
int m = 1; m < numMiddle; ++m){
1424 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1425 product_rc = explicitAdd(product_rc,product_m);
1427 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1430 blocked_product->endBlockFill();
1431 return blocked_product;
1435 if((isBlockedL && !isBlockedR)){
1436 double scalarl = 0.0;
1437 bool transpl =
false;
1438 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1439 double scalar = scalarl;
1441 int numRows = blocked_opl->productRange()->numBlocks();
1445 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1447 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1448 blocked_product->beginBlockFill(numRows,numCols);
1449 for(
int r = 0; r < numRows; ++r){
1450 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1451 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1453 blocked_product->endBlockFill();
1454 return blocked_product;
1458 if((!isBlockedL && isBlockedR)){
1459 double scalarr = 0.0;
1460 bool transpr =
false;
1461 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1462 double scalar = scalarr;
1465 int numCols = blocked_opr->productDomain()->numBlocks();
1468 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1470 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1471 blocked_product->beginBlockFill(numRows,numCols);
1472 for(
int c = 0; c < numCols; ++c){
1473 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1474 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1476 blocked_product->endBlockFill();
1477 return blocked_product;
1480 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1481 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1483 if(isTpetral && isTpetrar){
1486 bool transpl =
false;
1487 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1489 bool transpr =
false;
1490 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1493 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1494 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1497 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1498 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1499 explicitCrsOp->resumeFill();
1500 explicitCrsOp->scale(scalarl*scalarr);
1501 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1502 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1505 }
else if (isTpetral && !isTpetrar){
1509 bool transpl =
false;
1510 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1513 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opr,
true);
1514 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1515 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1516 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()));
1518 explicitCrsOp->rightScale(*diagPtr);
1519 explicitCrsOp->resumeFill();
1520 explicitCrsOp->scale(scalarl);
1521 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1523 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1525 }
else if (!isTpetral && isTpetrar){
1529 bool transpr =
false;
1530 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1532 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1535 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opl);
1536 if(dOpl != Teuchos::null){
1537 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1538 diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1541 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opl) != Teuchos::null){
1542 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpr->getRangeMap()));
1545 TEUCHOS_ASSERT(
false);
1547 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()));
1549 explicitCrsOp->leftScale(*diagPtr);
1550 explicitCrsOp->resumeFill();
1551 explicitCrsOp->scale(scalarr);
1552 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1554 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1559 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1562 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1563 = Thyra::epetraExtDiagScalingTransformer();
1567 if(not prodTrans->isCompatible(*implicitOp))
1568 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1571 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1572 prodTrans->transform(*implicitOp,explicitOp.ptr());
1573 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1574 " * " + opr->getObjectLabel() +
" )");
1593 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr,
1594 const ModifiableLinearOp & destOp)
1599 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1600 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1603 if((isBlockedL && isBlockedR)){
1604 double scalarl = 0.0;
1605 bool transpl =
false;
1606 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1607 double scalarr = 0.0;
1608 bool transpr =
false;
1609 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1610 double scalar = scalarl*scalarr;
1612 int numRows = blocked_opl->productRange()->numBlocks();
1613 int numCols = blocked_opr->productDomain()->numBlocks();
1614 int numMiddle = blocked_opl->productDomain()->numBlocks();
1616 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1618 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1619 blocked_product->beginBlockFill(numRows,numCols);
1620 for(
int r = 0; r < numRows; ++r){
1621 for(
int c = 0; c < numCols; ++c){
1623 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1624 for(
int m = 1; m < numMiddle; ++m){
1625 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1626 product_rc = explicitAdd(product_rc,product_m);
1628 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1631 blocked_product->endBlockFill();
1632 return blocked_product;
1636 if((isBlockedL && !isBlockedR)){
1637 double scalarl = 0.0;
1638 bool transpl =
false;
1639 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1640 double scalar = scalarl;
1642 int numRows = blocked_opl->productRange()->numBlocks();
1646 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1648 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1649 blocked_product->beginBlockFill(numRows,numCols);
1650 for(
int r = 0; r < numRows; ++r){
1651 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1652 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1654 blocked_product->endBlockFill();
1655 return blocked_product;
1659 if((!isBlockedL && isBlockedR)){
1660 double scalarr = 0.0;
1661 bool transpr =
false;
1662 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1663 double scalar = scalarr;
1666 int numCols = blocked_opr->productDomain()->numBlocks();
1669 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1671 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1672 blocked_product->beginBlockFill(numRows,numCols);
1673 for(
int c = 0; c < numCols; ++c){
1674 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1675 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1677 blocked_product->endBlockFill();
1678 return blocked_product;
1681 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1682 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1684 if(isTpetral && isTpetrar){
1688 bool transpl =
false;
1689 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1691 bool transpr =
false;
1692 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1695 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1696 if(destOp!=Teuchos::null)
1697 explicitOp = destOp;
1699 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1700 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1703 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1704 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1705 explicitCrsOp->resumeFill();
1706 explicitCrsOp->scale(scalarl*scalarr);
1707 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1708 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1711 }
else if (isTpetral && !isTpetrar){
1715 bool transpl =
false;
1716 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1719 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opr);
1720 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1721 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1724 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()));
1725 explicitCrsOp->rightScale(*diagPtr);
1726 explicitCrsOp->resumeFill();
1727 explicitCrsOp->scale(scalarl);
1728 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1729 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1731 }
else if (!isTpetral && isTpetrar){
1735 bool transpr =
false;
1736 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1739 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opl,
true);
1740 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1741 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1744 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()));
1745 explicitCrsOp->leftScale(*diagPtr);
1746 explicitCrsOp->resumeFill();
1747 explicitCrsOp->scale(scalarr);
1748 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1749 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1754 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1758 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1759 = Thyra::epetraExtDiagScalingTransformer();
1763 if(not prodTrans->isCompatible(*implicitOp))
1764 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1767 ModifiableLinearOp explicitOp;
1770 if(destOp==Teuchos::null)
1771 explicitOp = prodTrans->createOutputOp();
1773 explicitOp = destOp;
1776 prodTrans->transform(*implicitOp,explicitOp.ptr());
1779 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1780 " * " + opr->getObjectLabel() +
" )");
1796 const LinearOp explicitAdd(
const LinearOp & opl_in,
const LinearOp & opr_in)
1799 if(isPhysicallyBlockedLinearOp(opl_in) && isPhysicallyBlockedLinearOp(opr_in)){
1800 double scalarl = 0.0;
1801 bool transpl =
false;
1802 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl_in, &scalarl, &transpl);
1804 double scalarr = 0.0;
1805 bool transpr =
false;
1806 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr_in, &scalarr, &transpr);
1808 int numRows = blocked_opl->productRange()->numBlocks();
1809 int numCols = blocked_opl->productDomain()->numBlocks();
1810 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1811 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1813 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1814 blocked_sum->beginBlockFill(numRows,numCols);
1815 for(
int r = 0; r < numRows; ++r)
1816 for(
int c = 0; c < numCols; ++c)
1817 blocked_sum->setBlock(r,c,explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c))));
1818 blocked_sum->endBlockFill();
1823 LinearOp opl = opl_in;
1824 LinearOp opr = opr_in;
1825 if(isPhysicallyBlockedLinearOp(opl_in)){
1826 double scalarl = 0.0;
1827 bool transpl =
false;
1828 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl_in, &scalarl, &transpl);
1829 TEUCHOS_ASSERT(blocked_opl->productRange()->numBlocks() == 1);
1830 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == 1);
1831 opl = Thyra::scale(scalarl,blocked_opl->getBlock(0,0));
1833 if(isPhysicallyBlockedLinearOp(opr_in)){
1834 double scalarr = 0.0;
1835 bool transpr =
false;
1836 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr_in, &scalarr, &transpr);
1837 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == 1);
1838 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == 1);
1839 opr = Thyra::scale(scalarr,blocked_opr->getBlock(0,0));
1842 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1843 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1851 bool transp =
false;
1852 auto crs_op = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalar, &transp);
1853 auto zero_crs = Tpetra::createCrsMatrix<ST,LO,GO,NT>(crs_op->getRowMap());
1854 zero_crs->fillComplete();
1855 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);
1858 return opr->clone();
1863 bool transp =
false;
1864 auto crs_op = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalar, &transp);
1865 auto zero_crs = Tpetra::createCrsMatrix<ST,LO,GO,NT>(crs_op->getRowMap());
1866 zero_crs->fillComplete();
1867 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);
1870 return opl->clone();
1873 if(isTpetral && isTpetrar){
1877 bool transpl =
false;
1878 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1880 bool transpr =
false;
1881 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1884 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1885 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1888 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1889 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1894 const LinearOp implicitOp = Thyra::add(opl,opr);
1897 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1898 Thyra::epetraExtAddTransformer();
1901 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1902 prodTrans->transform(*implicitOp,explicitOp.ptr());
1903 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1904 " + " + opr->getObjectLabel() +
" )");
1922 const ModifiableLinearOp explicitAdd(
const LinearOp & opl,
const LinearOp & opr,
1923 const ModifiableLinearOp & destOp)
1926 if(isPhysicallyBlockedLinearOp(opl)){
1927 TEUCHOS_ASSERT(isPhysicallyBlockedLinearOp(opr));
1929 double scalarl = 0.0;
1930 bool transpl =
false;
1931 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl, &scalarl, &transpl);
1933 double scalarr = 0.0;
1934 bool transpr =
false;
1935 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr, &scalarr, &transpr);
1937 int numRows = blocked_opl->productRange()->numBlocks();
1938 int numCols = blocked_opl->productDomain()->numBlocks();
1939 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1940 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1942 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Teuchos::rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<double>>(destOp);
1943 if(blocked_sum.is_null()) {
1945 blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1947 blocked_sum->beginBlockFill(numRows,numCols);
1948 for(
int r = 0; r < numRows; ++r) {
1949 for(
int c = 0; c < numCols; ++c) {
1950 auto block = explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c)),Teuchos::null);
1951 blocked_sum->setNonconstBlock(r,c,block);
1954 blocked_sum->endBlockFill();
1959 for(
int r = 0; r < numRows; ++r)
1960 for(
int c = 0; c < numCols; ++c)
1961 explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c)),blocked_sum->getNonconstBlock(r,c));
1967 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1968 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1970 if(isTpetral && isTpetrar){
1974 bool transpl =
false;
1975 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1977 bool transpr =
false;
1978 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1981 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1982 if(destOp!=Teuchos::null)
1983 explicitOp = destOp;
1985 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1986 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1989 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1990 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1996 const LinearOp implicitOp = Thyra::add(opl,opr);
1999 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
2000 Thyra::epetraExtAddTransformer();
2003 RCP<Thyra::LinearOpBase<double> > explicitOp;
2004 if(destOp!=Teuchos::null)
2005 explicitOp = destOp;
2007 explicitOp = prodTrans->createOutputOp();
2010 prodTrans->transform(*implicitOp,explicitOp.ptr());
2011 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
2012 " + " + opr->getObjectLabel() +
" )");
2022 const ModifiableLinearOp explicitSum(
const LinearOp & op,
2023 const ModifiableLinearOp & destOp)
2026 const RCP<const Epetra_CrsMatrix> epetraOp =
2027 rcp_dynamic_cast<
const Epetra_CrsMatrix>(get_Epetra_Operator(*op),
true);
2029 if(destOp==Teuchos::null) {
2030 Teuchos::RCP<Epetra_Operator> epetraDest = Teuchos::rcp(
new Epetra_CrsMatrix(*epetraOp));
2032 return Thyra::nonconstEpetraLinearOp(epetraDest);
2035 const RCP<Epetra_CrsMatrix> epetraDest =
2036 rcp_dynamic_cast<Epetra_CrsMatrix>(get_Epetra_Operator(*destOp),
true);
2038 EpetraExt::MatrixMatrix::Add(*epetraOp,
false,1.0,*epetraDest,1.0);
2043 const LinearOp explicitTranspose(
const LinearOp & op)
2045 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2047 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op,
true);
2048 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
2050 Tpetra::RowMatrixTransposer<ST,LO,GO,NT> transposer(tCrsOp);
2051 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > transOp = transposer.createTranspose();
2053 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getDomainMap()),transOp);
2057 RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2058 TEUCHOS_TEST_FOR_EXCEPTION(eOp==Teuchos::null,std::logic_error,
2059 "Teko::explicitTranspose Not an Epetra_Operator");
2060 RCP<const Epetra_RowMatrix> eRowMatrixOp
2061 = Teuchos::rcp_dynamic_cast<
const Epetra_RowMatrix>(eOp);
2062 TEUCHOS_TEST_FOR_EXCEPTION(eRowMatrixOp==Teuchos::null,std::logic_error,
2063 "Teko::explicitTranspose Not an Epetra_RowMatrix");
2066 EpetraExt::RowMatrix_Transpose tranposeOp;
2067 Epetra_RowMatrix & eMat = tranposeOp(const_cast<Epetra_RowMatrix &>(*eRowMatrixOp));
2071 Teuchos::RCP<Epetra_CrsMatrix> crsMat
2072 = Teuchos::rcp(
new Epetra_CrsMatrix(dynamic_cast<Epetra_CrsMatrix &>(eMat)));
2074 return Thyra::epetraLinearOp(crsMat);
2078 double frobeniusNorm(
const LinearOp & op_in)
2081 double scalar = 1.0;
2084 if(isPhysicallyBlockedLinearOp(op_in)){
2085 bool transp =
false;
2086 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = getPhysicallyBlockedLinearOp(op_in,&scalar,&transp);
2087 TEUCHOS_ASSERT(blocked_op->productRange()->numBlocks() == 1);
2088 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == 1);
2089 op = blocked_op->getBlock(0,0);
2093 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2094 const RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
2095 const RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > crsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
2096 return crsOp->getFrobeniusNorm();
2098 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2099 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epOp,
true);
2100 return crsOp->NormFrobenius();
2104 double oneNorm(
const LinearOp & op)
2106 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2107 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"One norm not currently implemented for Tpetra matrices");
2110 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2111 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epOp,
true);
2112 return crsOp->NormOne();
2116 double infNorm(
const LinearOp & op)
2118 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2120 bool transp =
false;
2121 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
2124 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
2125 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
2128 diag.putScalar(0.0);
2129 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
2130 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
2131 std::vector<LO> indices(numEntries);
2132 std::vector<ST> values(numEntries);
2133 Teuchos::ArrayView<const LO> indices_av(indices);
2134 Teuchos::ArrayView<const ST> values_av(values);
2135 tCrsOp->getLocalRowView(i,indices_av,values_av);
2138 for(LO j=0;j<numEntries;j++)
2139 diag.sumIntoLocalValue(i,std::abs(values_av[j]));
2141 return diag.normInf()*scalar;
2144 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2145 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epOp,
true);
2146 return crsOp->NormInf();
2150 const LinearOp buildDiagonal(
const MultiVector & src,
const std::string & lbl)
2152 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(src->range());
2153 Thyra::copy(*src->col(0),dst.ptr());
2155 return Thyra::diagonal<double>(dst,lbl);
2158 const LinearOp buildInvDiagonal(
const MultiVector & src,
const std::string & lbl)
2160 const RCP<const Thyra::VectorBase<double> > srcV = src->col(0);
2161 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(srcV->range());
2162 Thyra::reciprocal<double>(*srcV,dst.ptr());
2164 return Thyra::diagonal<double>(dst,lbl);
2168 BlockedMultiVector buildBlockedMultiVector(
const std::vector<MultiVector> & mvv)
2170 Teuchos::Array<MultiVector> mvA;
2171 Teuchos::Array<VectorSpace> vsA;
2174 std::vector<MultiVector>::const_iterator itr;
2175 for(itr=mvv.begin();itr!=mvv.end();++itr) {
2176 mvA.push_back(*itr);
2177 vsA.push_back((*itr)->range());
2181 const RCP<const Thyra::DefaultProductVectorSpace<double> > vs
2182 = Thyra::productVectorSpace<double>(vsA);
2184 return Thyra::defaultProductMultiVector<double>(vs,mvA);
2197 Teuchos::RCP<Thyra::VectorBase<double> > indicatorVector(
2198 const std::vector<int> & indices,
2199 const VectorSpace & vs,
2200 double onValue,
double offValue)
2206 RCP<Thyra::VectorBase<double> > v = Thyra::createMember<double>(vs);
2207 Thyra::put_scalar<double>(offValue,v.ptr());
2210 for(std::size_t i=0;i<indices.size();i++)
2211 Thyra::set_ele<double>(indices[i],onValue,v.ptr());
2240 double computeSpectralRad(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2241 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2243 typedef Thyra::LinearOpBase<double> OP;
2244 typedef Thyra::MultiVectorBase<double> MV;
2246 int startVectors = 1;
2249 const RCP<MV> ivec = Thyra::createMember(A->domain());
2250 Thyra::randomize(-1.0,1.0,ivec.ptr());
2252 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2253 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2255 eigProb->setHermitian(isHermitian);
2258 if(not eigProb->setProblem()) {
2260 return Teuchos::ScalarTraits<double>::nan();
2264 std::string which(
"LM");
2268 Teuchos::ParameterList MyPL;
2269 MyPL.set(
"Verbosity", verbosity );
2270 MyPL.set(
"Which", which );
2271 MyPL.set(
"Block Size", startVectors );
2272 MyPL.set(
"Num Blocks", numBlocks );
2273 MyPL.set(
"Maximum Restarts", restart );
2274 MyPL.set(
"Convergence Tolerance", tol );
2282 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2285 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2287 if(solverreturn==Anasazi::Unconverged) {
2288 double real = MyBlockKrylovSchur.getRitzValues().begin()->realpart;
2289 double comp = MyBlockKrylovSchur.getRitzValues().begin()->imagpart;
2291 return -std::abs(std::sqrt(real*real+comp*comp));
2297 double real = eigProb->getSolution().Evals.begin()->realpart;
2298 double comp = eigProb->getSolution().Evals.begin()->imagpart;
2300 return std::abs(std::sqrt(real*real+comp*comp));
2330 double computeSmallestMagEig(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2331 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2333 typedef Thyra::LinearOpBase<double> OP;
2334 typedef Thyra::MultiVectorBase<double> MV;
2336 int startVectors = 1;
2339 const RCP<MV> ivec = Thyra::createMember(A->domain());
2340 Thyra::randomize(-1.0,1.0,ivec.ptr());
2342 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2343 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2345 eigProb->setHermitian(isHermitian);
2348 if(not eigProb->setProblem()) {
2350 return Teuchos::ScalarTraits<double>::nan();
2354 std::string which(
"SM");
2357 Teuchos::ParameterList MyPL;
2358 MyPL.set(
"Verbosity", verbosity );
2359 MyPL.set(
"Which", which );
2360 MyPL.set(
"Block Size", startVectors );
2361 MyPL.set(
"Num Blocks", numBlocks );
2362 MyPL.set(
"Maximum Restarts", restart );
2363 MyPL.set(
"Convergence Tolerance", tol );
2371 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2374 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2376 if(solverreturn==Anasazi::Unconverged) {
2378 return -std::abs(MyBlockKrylovSchur.getRitzValues().begin()->realpart);
2382 return std::abs(eigProb->getSolution().Evals.begin()->realpart);
2394 ModifiableLinearOp getDiagonalOp(
const Teko::LinearOp & A,
const DiagonalType & dt)
2398 return getDiagonalOp(A);
2400 return getLumpedMatrix(A);
2402 return getAbsRowSumMatrix(A);
2405 TEUCHOS_TEST_FOR_EXCEPT(
true);
2408 return Teuchos::null;
2419 ModifiableLinearOp getInvDiagonalOp(
const Teko::LinearOp & A,
const Teko::DiagonalType & dt)
2423 return getInvDiagonalOp(A);
2425 return getInvLumpedMatrix(A);
2427 return getAbsRowSumInvMatrix(A);
2430 TEUCHOS_TEST_FOR_EXCEPT(
true);
2433 return Teuchos::null;
2442 std::string getDiagonalName(
const DiagonalType & dt)
2470 if(name==
"Diagonal")
2474 if(name==
"AbsRowSum")
2482 LinearOp probe(Teuchos::RCP<const Epetra_CrsGraph> &G,
const LinearOp & Op){
2483 #ifdef Teko_ENABLE_Isorropia 2484 Teuchos::ParameterList probeList;
2485 Prober prober(G,probeList,
true);
2486 Teuchos::RCP<Epetra_CrsMatrix> Mat=rcp(
new Epetra_CrsMatrix(Copy,*G));
2488 prober.probe(Mwrap,*Mat);
2489 return Thyra::epetraLinearOp(Mat);
2493 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::runtime_error,
"Probe requires Isorropia");
2497 double norm_1(
const MultiVector & v,std::size_t col)
2499 Teuchos::Array<double> n(v->domain()->dim());
2500 Thyra::norms_1<double>(*v,n);
2505 double norm_2(
const MultiVector & v,std::size_t col)
2507 Teuchos::Array<double> n(v->domain()->dim());
2508 Thyra::norms_2<double>(*v,n);
2513 void putScalar(
const ModifiableLinearOp & op,
double scalar)
2517 RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2520 RCP<Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
2522 eCrsOp->PutScalar(scalar);
2524 catch (std::exception & e) {
2525 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
2527 *out <<
"Teko: putScalar requires an Epetra_CrsMatrix\n";
2528 *out <<
" Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
2530 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
2532 *out <<
"*** THROWN EXCEPTION ***\n";
2533 *out << e.what() << std::endl;
2534 *out <<
"************************\n";
2540 void clipLower(MultiVector & v,
double lowerBound)
2543 using Teuchos::rcp_dynamic_cast;
2549 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2550 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2551 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2553 Teuchos::ArrayRCP<double> values;
2555 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2556 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2557 if(values[j]<lowerBound)
2558 values[j] = lowerBound;
2563 void clipUpper(MultiVector & v,
double upperBound)
2566 using Teuchos::rcp_dynamic_cast;
2571 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2572 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2573 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2575 Teuchos::ArrayRCP<double> values;
2577 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2578 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2579 if(values[j]>upperBound)
2580 values[j] = upperBound;
2585 void replaceValue(MultiVector & v,
double currentValue,
double newValue)
2588 using Teuchos::rcp_dynamic_cast;
2593 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2594 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2595 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2597 Teuchos::ArrayRCP<double> values;
2599 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2600 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2601 if(values[j]==currentValue)
2602 values[j] = newValue;
2607 void columnAverages(
const MultiVector & v,std::vector<double> & averages)
2609 averages.resize(v->domain()->dim());
2612 Thyra::sums<double>(*v,averages);
2615 Thyra::Ordinal rows = v->range()->dim();
2616 for(std::size_t i=0;i<averages.size();i++)
2617 averages[i] = averages[i]/rows;
2620 double average(
const MultiVector & v)
2622 Thyra::Ordinal rows = v->range()->dim();
2623 Thyra::Ordinal cols = v->domain()->dim();
2625 std::vector<double> averages;
2626 columnAverages(v,averages);
2629 for(std::size_t i=0;i<averages.size();i++)
2630 sum += averages[i] * rows;
2632 return sum/(rows*cols);
2635 bool isPhysicallyBlockedLinearOp(
const LinearOp & op)
2638 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2639 if (!pblo.is_null())
2644 Thyra::EOpTransp transp = Thyra::NOTRANS;
2645 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2646 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
2647 pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op);
2648 if (!pblo.is_null())
2654 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > getPhysicallyBlockedLinearOp(
const LinearOp & op, ST *scalar,
bool *transp)
2657 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2658 if(!pblo.is_null()){
2665 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2666 Thyra::EOpTransp eTransp = Thyra::NOTRANS;
2667 Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
2668 pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op,
true);
2669 if(!pblo.is_null()){
2671 if(eTransp == Thyra::NOTRANS)
2676 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 .