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 const LinearOp test = rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<double> >(op);
615 return test!=Teuchos::null;
626 ModifiableLinearOp getAbsRowSumMatrix(
const LinearOp & op)
628 bool isTpetra =
false;
629 RCP<const Epetra_CrsMatrix> eCrsOp;
630 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
634 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<
const Thyra::EpetraLinearOp >(op);
635 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
638 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
640 eCrsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
642 else if (!tOp.is_null()){
643 tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
647 throw std::logic_error(
"Neither Epetra nor Tpetra");
649 catch (std::exception & e) {
650 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
652 *out <<
"Teko: getAbsRowSumMatrix requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
653 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
655 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
657 *out <<
"*** THROWN EXCEPTION ***\n";
658 *out << e.what() << std::endl;
659 *out <<
"************************\n";
666 const RCP<Epetra_Vector> ptrDiag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
667 Epetra_Vector & diag = *ptrDiag;
671 for(
int i=0;i<eCrsOp->NumMyRows();i++) {
674 eCrsOp->ExtractMyRowView(i,numEntries,values);
677 for(
int j=0;j<numEntries;j++)
678 diag[i] += std::abs(values[j]);
682 return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),
"absRowSum( " + op->getObjectLabel() +
" )");
686 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
687 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
691 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
692 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
693 std::vector<LO> indices(numEntries);
694 std::vector<ST> values(numEntries);
695 Teuchos::ArrayView<const LO> indices_av(indices);
696 Teuchos::ArrayView<const ST> values_av(values);
697 tCrsOp->getLocalRowView(i,indices_av,values_av);
700 for(LO j=0;j<numEntries;j++)
701 diag.sumIntoLocalValue(i,std::abs(values_av[j]));
705 return Teko::TpetraHelpers::thyraDiagOp(ptrDiag,*tCrsOp->getRowMap(),
"absRowSum( " + op->getObjectLabel() +
" ))");
719 ModifiableLinearOp getAbsRowSumInvMatrix(
const LinearOp & op)
722 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
723 if(blocked_op != Teuchos::null){
724 int numRows = blocked_op->productRange()->numBlocks();
725 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == numRows);
726 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_diag = Thyra::defaultBlockedLinearOp<double>();
727 blocked_diag->beginBlockFill(numRows,numRows);
728 for(
int r = 0; r < numRows; ++r){
729 for(
int c = 0; c < numRows; ++c){
731 blocked_diag->setNonconstBlock(r,c,getAbsRowSumInvMatrix(blocked_op->getBlock(r,c)));
733 blocked_diag->setBlock(r,c,Thyra::zero<double>(blocked_op->getBlock(r,c)->range(),blocked_op->getBlock(r,c)->domain()));
736 blocked_diag->endBlockFill();
740 if(Teko::TpetraHelpers::isTpetraLinearOp(op)) {
743 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
746 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
747 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
751 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
752 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
753 std::vector<LO> indices(numEntries);
754 std::vector<ST> values(numEntries);
755 Teuchos::ArrayView<const LO> indices_av(indices);
756 Teuchos::ArrayView<const ST> values_av(values);
757 tCrsOp->getLocalRowView(i,indices_av,values_av);
760 for(LO j=0;j<numEntries;j++)
761 diag.sumIntoLocalValue(i,std::abs(values_av[j]));
764 diag.reciprocal(diag);
767 return Teko::TpetraHelpers::thyraDiagOp(ptrDiag,*tCrsOp->getRowMap(),
"absRowSum( " + op->getObjectLabel() +
" ))");
771 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<
const Thyra::EpetraLinearOp >(op,
true);
772 RCP<const Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
775 const RCP<Epetra_Vector> ptrDiag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
776 Epetra_Vector & diag = *ptrDiag;
780 for(
int i=0;i<eCrsOp->NumMyRows();i++) {
783 eCrsOp->ExtractMyRowView(i,numEntries,values);
786 for(
int j=0;j<numEntries;j++)
787 diag[i] += std::abs(values[j]);
789 diag.Reciprocal(diag);
792 return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),
"absRowSum( " + op->getObjectLabel() +
" )");
804 ModifiableLinearOp getLumpedMatrix(
const LinearOp & op)
806 RCP<Thyra::VectorBase<ST> > ones = Thyra::createMember(op->domain());
807 RCP<Thyra::VectorBase<ST> > diag = Thyra::createMember(op->range());
810 Thyra::assign(ones.ptr(),1.0);
814 Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
816 return rcp(
new Thyra::DefaultDiagonalLinearOp<ST>(diag));
827 ModifiableLinearOp getInvLumpedMatrix(
const LinearOp & op)
829 RCP<Thyra::VectorBase<ST> > ones = Thyra::createMember(op->domain());
830 RCP<Thyra::VectorBase<ST> > diag = Thyra::createMember(op->range());
833 Thyra::assign(ones.ptr(),1.0);
836 Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
837 Thyra::reciprocal(*diag,diag.ptr());
839 return rcp(
new Thyra::DefaultDiagonalLinearOp<ST>(diag));
853 const ModifiableLinearOp getDiagonalOp(
const LinearOp & op)
855 bool isTpetra =
false;
856 RCP<const Epetra_CrsMatrix> eCrsOp;
857 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
861 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<
const Thyra::EpetraLinearOp >(op);
862 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
865 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
867 eCrsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
869 else if (!tOp.is_null()){
870 tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
874 throw std::logic_error(
"Neither Epetra nor Tpetra");
876 catch (std::exception & e) {
877 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
879 *out <<
"Teko: getDiagonalOp requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
880 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
882 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
884 *out <<
"*** THROWN EXCEPTION ***\n";
885 *out << e.what() << std::endl;
886 *out <<
"************************\n";
893 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
894 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
897 return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
901 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
902 tCrsOp->getLocalDiagCopy(*diag);
905 return Teko::TpetraHelpers::thyraDiagOp(diag,*tCrsOp->getRowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
910 const MultiVector getDiagonal(
const LinearOp & op)
912 bool isTpetra =
false;
913 RCP<const Epetra_CrsMatrix> eCrsOp;
914 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
918 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<
const Thyra::EpetraLinearOp >(op);
919 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
922 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
924 eCrsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
926 else if (!tOp.is_null()){
927 tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
931 throw std::logic_error(
"Neither Epetra nor Tpetra");
933 catch (std::exception & e) {
934 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
936 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<
const Thyra::EpetraLinearOp >(op);
937 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
941 *out <<
"Teko: getDiagonal requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
942 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
944 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
946 *out <<
"*** THROWN EXCEPTION ***\n";
947 *out << e.what() << std::endl;
948 *out <<
"************************\n";
955 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
956 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
958 return Thyra::create_Vector(diag,Thyra::create_VectorSpace(Teuchos::rcpFromRef(eCrsOp->RowMap())));
962 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
963 tCrsOp->getLocalDiagCopy(*diag);
966 return Thyra::createVector<ST,LO,GO,NT>(diag,Thyra::createVectorSpace<ST,LO,GO,NT>(tCrsOp->getRowMap()));
971 const MultiVector getDiagonal(
const Teko::LinearOp & A,
const DiagonalType & dt)
973 LinearOp diagOp = Teko::getDiagonalOp(A,dt);
975 Teuchos::RCP<const Thyra::MultiVectorBase<double> > v =
976 Teuchos::rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<double> >(diagOp)->getDiag();
977 return Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(v);
991 const ModifiableLinearOp getInvDiagonalOp(
const LinearOp & op)
993 if (Teko::TpetraHelpers::isTpetraLinearOp(op)){
996 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
999 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
1000 diag->scale(scalar);
1001 tCrsOp->getLocalDiagCopy(*diag);
1002 diag->reciprocal(*diag);
1005 return Teko::TpetraHelpers::thyraDiagOp(diag,*tCrsOp->getRowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
1009 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<
const Thyra::EpetraLinearOp >(op,
true);
1010 RCP<const Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
1013 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
1014 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
1015 diag->Reciprocal(*diag);
1018 return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
1034 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opm,
const LinearOp & opr)
1039 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1040 bool isBlockedM = isPhysicallyBlockedLinearOp(opm);
1041 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1044 if((isBlockedL && isBlockedM && isBlockedR)){
1046 double scalarl = 0.0;
1047 bool transpl =
false;
1048 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1049 double scalarm = 0.0;
1050 bool transpm =
false;
1051 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opm = getPhysicallyBlockedLinearOp(opm,&scalarm,&transpm);
1052 double scalarr = 0.0;
1053 bool transpr =
false;
1054 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1055 double scalar = scalarl*scalarm*scalarr;
1057 int numRows = blocked_opl->productRange()->numBlocks();
1058 int numCols = blocked_opr->productDomain()->numBlocks();
1059 int numMiddle = blocked_opm->productRange()->numBlocks();
1062 TEUCHOS_ASSERT(blocked_opm->productDomain()->numBlocks() == numMiddle);
1063 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1064 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1066 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1067 blocked_product->beginBlockFill(numRows,numCols);
1068 for(
int r = 0; r < numRows; ++r){
1069 for(
int c = 0; c < numCols; ++c){
1070 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opm->getBlock(0,0),blocked_opr->getBlock(0,c));
1071 for(
int m = 1; m < numMiddle; ++m){
1072 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opm->getBlock(m,m),blocked_opr->getBlock(m,c));
1073 product_rc = explicitAdd(product_rc,product_m);
1075 blocked_product->setBlock(r,c,product_rc);
1078 blocked_product->endBlockFill();
1079 return Thyra::scale<double>(scalar,blocked_product.getConst());
1083 if(isBlockedL && !isBlockedM && isBlockedR){
1084 double scalarl = 0.0;
1085 bool transpl =
false;
1086 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1087 double scalarr = 0.0;
1088 bool transpr =
false;
1089 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1090 double scalar = scalarl*scalarr;
1092 int numRows = blocked_opl->productRange()->numBlocks();
1093 int numCols = blocked_opr->productDomain()->numBlocks();
1097 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1098 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1100 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1101 blocked_product->beginBlockFill(numRows,numCols);
1102 for(
int r = 0; r < numRows; ++r){
1103 for(
int c = 0; c < numCols; ++c){
1104 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),opm,blocked_opr->getBlock(0,c));
1105 blocked_product->setBlock(r,c,product_rc);
1108 blocked_product->endBlockFill();
1109 return Thyra::scale<double>(scalar,blocked_product.getConst());
1113 if(!isBlockedL && !isBlockedM && isBlockedR){
1114 double scalarr = 0.0;
1115 bool transpr =
false;
1116 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1117 double scalar = scalarr;
1120 int numCols = blocked_opr->productDomain()->numBlocks();
1124 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1126 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1127 blocked_product->beginBlockFill(numRows,numCols);
1128 for(
int c = 0; c < numCols; ++c){
1129 LinearOp product_c = explicitMultiply(opl,opm,blocked_opr->getBlock(0,c));
1130 blocked_product->setBlock(0,c,product_c);
1132 blocked_product->endBlockFill();
1133 return Thyra::scale<double>(scalar,blocked_product.getConst());
1138 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1139 bool isTpetram = Teko::TpetraHelpers::isTpetraLinearOp(opm);
1140 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1142 if(isTpetral && isTpetram && isTpetrar){
1146 bool transpl =
false;
1147 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1149 bool transpm =
false;
1150 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpm = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarm, &transpm);
1152 bool transpr =
false;
1153 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1156 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1157 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1160 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1161 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1162 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1163 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1164 explicitCrsOp->resumeFill();
1165 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1166 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1167 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1170 }
else if (isTpetral && !isTpetram && isTpetrar){
1174 bool transpl =
false;
1175 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1177 bool transpr =
false;
1178 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1180 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1183 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opm);
1184 if(dOpm != Teuchos::null){
1185 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1186 diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1189 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opm) != Teuchos::null){
1190 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpl->getDomainMap()));
1193 TEUCHOS_ASSERT(
false);
1195 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()));
1198 tCrsOplm->rightScale(*diagPtr);
1201 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1202 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1205 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1206 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1207 explicitCrsOp->resumeFill();
1208 explicitCrsOp->scale(scalarl*scalarr);
1209 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1210 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1216 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1219 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1220 Thyra::epetraExtDiagScaledMatProdTransformer();
1223 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1224 prodTrans->transform(*implicitOp,explicitOp.ptr());
1225 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1226 " * " + opm->getObjectLabel() +
1227 " * " + opr->getObjectLabel() +
" )");
1248 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opm,
const LinearOp & opr,
1249 const ModifiableLinearOp & destOp)
1251 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1252 bool isTpetram = Teko::TpetraHelpers::isTpetraLinearOp(opm);
1253 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1255 if(isTpetral && isTpetram && isTpetrar){
1259 bool transpl =
false;
1260 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1262 bool transpm =
false;
1263 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpm = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarm, &transpm);
1265 bool transpr =
false;
1266 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1269 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1270 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1273 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1274 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1275 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1276 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1277 explicitCrsOp->resumeFill();
1278 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1279 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1280 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1283 }
else if (isTpetral && !isTpetram && isTpetrar){
1287 bool transpl =
false;
1288 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1290 bool transpr =
false;
1291 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1294 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opm,
true);
1295 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1296 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1297 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()));
1300 tCrsOplm->rightScale(*diagPtr);
1303 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1304 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1307 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1308 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1309 explicitCrsOp->resumeFill();
1310 explicitCrsOp->scale(scalarl*scalarr);
1311 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1312 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1318 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1321 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1322 Thyra::epetraExtDiagScaledMatProdTransformer();
1325 ModifiableLinearOp explicitOp;
1328 if(destOp==Teuchos::null)
1329 explicitOp = prodTrans->createOutputOp();
1331 explicitOp = destOp;
1334 prodTrans->transform(*implicitOp,explicitOp.ptr());
1337 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1338 " * " + opm->getObjectLabel() +
1339 " * " + opr->getObjectLabel() +
" )");
1356 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr)
1361 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1362 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1365 if((isBlockedL && isBlockedR)){
1366 double scalarl = 0.0;
1367 bool transpl =
false;
1368 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1369 double scalarr = 0.0;
1370 bool transpr =
false;
1371 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1372 double scalar = scalarl*scalarr;
1374 int numRows = blocked_opl->productRange()->numBlocks();
1375 int numCols = blocked_opr->productDomain()->numBlocks();
1376 int numMiddle = blocked_opl->productDomain()->numBlocks();
1378 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1380 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1381 blocked_product->beginBlockFill(numRows,numCols);
1382 for(
int r = 0; r < numRows; ++r){
1383 for(
int c = 0; c < numCols; ++c){
1384 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1385 for(
int m = 1; m < numMiddle; ++m){
1386 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1387 product_rc = explicitAdd(product_rc,product_m);
1389 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1392 blocked_product->endBlockFill();
1393 return blocked_product;
1397 if((isBlockedL && !isBlockedR)){
1398 double scalarl = 0.0;
1399 bool transpl =
false;
1400 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1401 double scalar = scalarl;
1403 int numRows = blocked_opl->productRange()->numBlocks();
1407 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1409 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1410 blocked_product->beginBlockFill(numRows,numCols);
1411 for(
int r = 0; r < numRows; ++r){
1412 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1413 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1415 blocked_product->endBlockFill();
1416 return blocked_product;
1420 if((!isBlockedL && isBlockedR)){
1421 double scalarr = 0.0;
1422 bool transpr =
false;
1423 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1424 double scalar = scalarr;
1427 int numCols = blocked_opr->productDomain()->numBlocks();
1430 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1432 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1433 blocked_product->beginBlockFill(numRows,numCols);
1434 for(
int c = 0; c < numCols; ++c){
1435 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1436 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1438 blocked_product->endBlockFill();
1439 return blocked_product;
1442 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1443 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1445 if(isTpetral && isTpetrar){
1448 bool transpl =
false;
1449 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1451 bool transpr =
false;
1452 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1455 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1456 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1459 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1460 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1461 explicitCrsOp->resumeFill();
1462 explicitCrsOp->scale(scalarl*scalarr);
1463 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1464 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1467 }
else if (isTpetral && !isTpetrar){
1471 bool transpl =
false;
1472 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1475 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opr,
true);
1476 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1477 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1478 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()));
1480 explicitCrsOp->rightScale(*diagPtr);
1481 explicitCrsOp->resumeFill();
1482 explicitCrsOp->scale(scalarl);
1483 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1485 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1487 }
else if (!isTpetral && isTpetrar){
1491 bool transpr =
false;
1492 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1494 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1497 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opl);
1498 if(dOpl != Teuchos::null){
1499 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1500 diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1503 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opl) != Teuchos::null){
1504 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpr->getRangeMap()));
1507 TEUCHOS_ASSERT(
false);
1509 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()));
1511 explicitCrsOp->leftScale(*diagPtr);
1512 explicitCrsOp->resumeFill();
1513 explicitCrsOp->scale(scalarr);
1514 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1516 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1521 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1524 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1525 = Thyra::epetraExtDiagScalingTransformer();
1529 if(not prodTrans->isCompatible(*implicitOp))
1530 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1533 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1534 prodTrans->transform(*implicitOp,explicitOp.ptr());
1535 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1536 " * " + opr->getObjectLabel() +
" )");
1555 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr,
1556 const ModifiableLinearOp & destOp)
1561 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1562 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1565 if((isBlockedL && isBlockedR)){
1566 double scalarl = 0.0;
1567 bool transpl =
false;
1568 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1569 double scalarr = 0.0;
1570 bool transpr =
false;
1571 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1572 double scalar = scalarl*scalarr;
1574 int numRows = blocked_opl->productRange()->numBlocks();
1575 int numCols = blocked_opr->productDomain()->numBlocks();
1576 int numMiddle = blocked_opl->productDomain()->numBlocks();
1578 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1580 std::cout <<
"rows, cols, middle = " << numRows <<
", " << numCols <<
", " << numMiddle << std::endl;
1582 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1583 blocked_product->beginBlockFill(numRows,numCols);
1584 for(
int r = 0; r < numRows; ++r){
1585 for(
int c = 0; c < numCols; ++c){
1587 std::cout <<
"Block multiply " << r <<
", " << c << std::endl;
1588 std::cout << blocked_opl->getBlock(r,0)->range()->dim() <<
" x " << blocked_opl->getBlock(r,0)->domain()->dim() <<
" times ";
1589 std::cout << blocked_opr->getBlock(0,c)->range()->dim() <<
" x " << blocked_opr->getBlock(0,c)->domain()->dim() << std::endl;
1591 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1592 for(
int m = 1; m < numMiddle; ++m){
1593 std::cout << blocked_opl->getBlock(r,m)->range()->dim() <<
" x " << blocked_opl->getBlock(r,m)->domain()->dim() <<
" times ";
1594 std::cout << blocked_opr->getBlock(m,c)->range()->dim() <<
" x " << blocked_opr->getBlock(m,c)->domain()->dim() << std::endl;
1595 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1596 product_rc = explicitAdd(product_rc,product_m);
1598 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1601 blocked_product->endBlockFill();
1602 return blocked_product;
1606 if((isBlockedL && !isBlockedR)){
1607 double scalarl = 0.0;
1608 bool transpl =
false;
1609 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1610 double scalar = scalarl;
1612 int numRows = blocked_opl->productRange()->numBlocks();
1616 TEUCHOS_ASSERT(blocked_opl->productDomain()->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 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1622 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1624 blocked_product->endBlockFill();
1625 return blocked_product;
1629 if((!isBlockedL && isBlockedR)){
1630 double scalarr = 0.0;
1631 bool transpr =
false;
1632 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1633 double scalar = scalarr;
1636 int numCols = blocked_opr->productDomain()->numBlocks();
1639 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1641 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1642 blocked_product->beginBlockFill(numRows,numCols);
1643 for(
int c = 0; c < numCols; ++c){
1644 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1645 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1647 blocked_product->endBlockFill();
1648 return blocked_product;
1651 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1652 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1654 if(isTpetral && isTpetrar){
1658 bool transpl =
false;
1659 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1661 bool transpr =
false;
1662 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1665 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1666 if(destOp!=Teuchos::null)
1667 explicitOp = destOp;
1669 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1670 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1673 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1674 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1675 explicitCrsOp->resumeFill();
1676 explicitCrsOp->scale(scalarl*scalarr);
1677 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1678 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1681 }
else if (isTpetral && !isTpetrar){
1685 bool transpl =
false;
1686 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1689 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opr);
1690 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1691 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1694 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()));
1695 explicitCrsOp->rightScale(*diagPtr);
1696 explicitCrsOp->resumeFill();
1697 explicitCrsOp->scale(scalarl);
1698 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1699 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1701 }
else if (!isTpetral && isTpetrar){
1705 bool transpr =
false;
1706 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1709 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<ST> >(opl,
true);
1710 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<
const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1711 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<
const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1714 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()));
1715 explicitCrsOp->leftScale(*diagPtr);
1716 explicitCrsOp->resumeFill();
1717 explicitCrsOp->scale(scalarr);
1718 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1719 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1724 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1728 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1729 = Thyra::epetraExtDiagScalingTransformer();
1733 if(not prodTrans->isCompatible(*implicitOp))
1734 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1737 ModifiableLinearOp explicitOp;
1740 if(destOp==Teuchos::null)
1741 explicitOp = prodTrans->createOutputOp();
1743 explicitOp = destOp;
1746 prodTrans->transform(*implicitOp,explicitOp.ptr());
1749 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1750 " * " + opr->getObjectLabel() +
" )");
1766 const LinearOp explicitAdd(
const LinearOp & opl,
const LinearOp & opr)
1769 if(isPhysicallyBlockedLinearOp(opl)){
1770 TEUCHOS_ASSERT(isPhysicallyBlockedLinearOp(opr));
1772 double scalarl = 0.0;
1773 bool transpl =
false;
1774 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl, &scalarl, &transpl);
1776 double scalarr = 0.0;
1777 bool transpr =
false;
1778 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr, &scalarr, &transpr);
1780 int numRows = blocked_opl->productRange()->numBlocks();
1781 int numCols = blocked_opl->productDomain()->numBlocks();
1782 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1783 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1785 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1786 blocked_sum->beginBlockFill(numRows,numCols);
1787 for(
int r = 0; r < numRows; ++r)
1788 for(
int c = 0; c < numCols; ++c)
1789 blocked_sum->setBlock(r,c,explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c))));
1790 blocked_sum->endBlockFill();
1794 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1795 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1797 if(isTpetral && isTpetrar){
1801 bool transpl =
false;
1802 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1804 bool transpr =
false;
1805 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1808 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1809 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1812 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1813 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1818 const LinearOp implicitOp = Thyra::add(opl,opr);
1821 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1822 Thyra::epetraExtAddTransformer();
1825 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1826 prodTrans->transform(*implicitOp,explicitOp.ptr());
1827 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1828 " + " + opr->getObjectLabel() +
" )");
1846 const ModifiableLinearOp explicitAdd(
const LinearOp & opl,
const LinearOp & opr,
1847 const ModifiableLinearOp & destOp)
1850 if(isPhysicallyBlockedLinearOp(opl)){
1851 TEUCHOS_ASSERT(isPhysicallyBlockedLinearOp(opr));
1853 double scalarl = 0.0;
1854 bool transpl =
false;
1855 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl, &scalarl, &transpl);
1857 double scalarr = 0.0;
1858 bool transpr =
false;
1859 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr, &scalarr, &transpr);
1861 int numRows = blocked_opl->productRange()->numBlocks();
1862 int numCols = blocked_opl->productDomain()->numBlocks();
1863 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1864 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1866 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1867 blocked_sum->beginBlockFill(numRows,numCols);
1868 for(
int r = 0; r < numRows; ++r)
1869 for(
int c = 0; c < numCols; ++c)
1870 blocked_sum->setBlock(r,c,explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c))));
1871 blocked_sum->endBlockFill();
1875 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1876 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1878 if(isTpetral && isTpetrar){
1882 bool transpl =
false;
1883 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1885 bool transpr =
false;
1886 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1889 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1890 if(destOp!=Teuchos::null)
1891 explicitOp = destOp;
1893 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1894 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1897 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1898 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1904 const LinearOp implicitOp = Thyra::add(opl,opr);
1907 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1908 Thyra::epetraExtAddTransformer();
1911 RCP<Thyra::LinearOpBase<double> > explicitOp;
1912 if(destOp!=Teuchos::null)
1913 explicitOp = destOp;
1915 explicitOp = prodTrans->createOutputOp();
1918 prodTrans->transform(*implicitOp,explicitOp.ptr());
1919 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1920 " + " + opr->getObjectLabel() +
" )");
1930 const ModifiableLinearOp explicitSum(
const LinearOp & op,
1931 const ModifiableLinearOp & destOp)
1934 const RCP<const Epetra_CrsMatrix> epetraOp =
1935 rcp_dynamic_cast<
const Epetra_CrsMatrix>(get_Epetra_Operator(*op),
true);
1937 if(destOp==Teuchos::null) {
1938 Teuchos::RCP<Epetra_Operator> epetraDest = Teuchos::rcp(
new Epetra_CrsMatrix(*epetraOp));
1940 return Thyra::nonconstEpetraLinearOp(epetraDest);
1943 const RCP<Epetra_CrsMatrix> epetraDest =
1944 rcp_dynamic_cast<Epetra_CrsMatrix>(get_Epetra_Operator(*destOp),
true);
1946 EpetraExt::MatrixMatrix::Add(*epetraOp,
false,1.0,*epetraDest,1.0);
1951 const LinearOp explicitTranspose(
const LinearOp & op)
1953 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
1955 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op,
true);
1956 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
1958 Tpetra::RowMatrixTransposer<ST,LO,GO,NT> transposer(tCrsOp);
1959 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > transOp = transposer.createTranspose();
1961 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getDomainMap()),transOp);
1965 RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
1966 TEUCHOS_TEST_FOR_EXCEPTION(eOp==Teuchos::null,std::logic_error,
1967 "Teko::explicitTranspose Not an Epetra_Operator");
1968 RCP<const Epetra_RowMatrix> eRowMatrixOp
1969 = Teuchos::rcp_dynamic_cast<
const Epetra_RowMatrix>(eOp);
1970 TEUCHOS_TEST_FOR_EXCEPTION(eRowMatrixOp==Teuchos::null,std::logic_error,
1971 "Teko::explicitTranspose Not an Epetra_RowMatrix");
1974 EpetraExt::RowMatrix_Transpose tranposeOp;
1975 Epetra_RowMatrix & eMat = tranposeOp(const_cast<Epetra_RowMatrix &>(*eRowMatrixOp));
1979 Teuchos::RCP<Epetra_CrsMatrix> crsMat
1980 = Teuchos::rcp(
new Epetra_CrsMatrix(dynamic_cast<Epetra_CrsMatrix &>(eMat)));
1982 return Thyra::epetraLinearOp(crsMat);
1986 double frobeniusNorm(
const LinearOp & op)
1988 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
1989 const RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<
const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
1990 const RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > crsOp = rcp_dynamic_cast<
const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
1991 return crsOp->getFrobeniusNorm();
1993 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
1994 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epOp,
true);
1995 return crsOp->NormFrobenius();
1999 double oneNorm(
const LinearOp & op)
2001 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2005 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"One norm not currently implemented for Tpetra matrices");
2007 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2008 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epOp,
true);
2009 return crsOp->NormOne();
2013 double infNorm(
const LinearOp & op)
2015 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2019 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"Infinity norm not currently implemented for Tpetra matrices");
2021 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2022 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epOp,
true);
2023 return crsOp->NormInf();
2027 const LinearOp buildDiagonal(
const MultiVector & src,
const std::string & lbl)
2029 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(src->range());
2030 Thyra::copy(*src->col(0),dst.ptr());
2032 return Thyra::diagonal<double>(dst,lbl);
2035 const LinearOp buildInvDiagonal(
const MultiVector & src,
const std::string & lbl)
2037 const RCP<const Thyra::VectorBase<double> > srcV = src->col(0);
2038 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(srcV->range());
2039 Thyra::reciprocal<double>(*srcV,dst.ptr());
2041 return Thyra::diagonal<double>(dst,lbl);
2045 BlockedMultiVector buildBlockedMultiVector(
const std::vector<MultiVector> & mvv)
2047 Teuchos::Array<MultiVector> mvA;
2048 Teuchos::Array<VectorSpace> vsA;
2051 std::vector<MultiVector>::const_iterator itr;
2052 for(itr=mvv.begin();itr!=mvv.end();++itr) {
2053 mvA.push_back(*itr);
2054 vsA.push_back((*itr)->range());
2058 const RCP<const Thyra::DefaultProductVectorSpace<double> > vs
2059 = Thyra::productVectorSpace<double>(vsA);
2061 return Thyra::defaultProductMultiVector<double>(vs,mvA);
2074 Teuchos::RCP<Thyra::VectorBase<double> > indicatorVector(
2075 const std::vector<int> & indices,
2076 const VectorSpace & vs,
2077 double onValue,
double offValue)
2083 RCP<Thyra::VectorBase<double> > v = Thyra::createMember<double>(vs);
2084 Thyra::put_scalar<double>(offValue,v.ptr());
2087 for(std::size_t i=0;i<indices.size();i++)
2088 Thyra::set_ele<double>(indices[i],onValue,v.ptr());
2117 double computeSpectralRad(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2118 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2120 typedef Thyra::LinearOpBase<double> OP;
2121 typedef Thyra::MultiVectorBase<double> MV;
2123 int startVectors = 1;
2126 const RCP<MV> ivec = Thyra::createMember(A->domain());
2127 Thyra::randomize(-1.0,1.0,ivec.ptr());
2129 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2130 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2132 eigProb->setHermitian(isHermitian);
2135 if(not eigProb->setProblem()) {
2137 return Teuchos::ScalarTraits<double>::nan();
2141 std::string which(
"LM");
2145 Teuchos::ParameterList MyPL;
2146 MyPL.set(
"Verbosity", verbosity );
2147 MyPL.set(
"Which", which );
2148 MyPL.set(
"Block Size", startVectors );
2149 MyPL.set(
"Num Blocks", numBlocks );
2150 MyPL.set(
"Maximum Restarts", restart );
2151 MyPL.set(
"Convergence Tolerance", tol );
2159 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2162 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2164 if(solverreturn==Anasazi::Unconverged) {
2165 double real = MyBlockKrylovSchur.getRitzValues().begin()->realpart;
2166 double comp = MyBlockKrylovSchur.getRitzValues().begin()->imagpart;
2168 return -std::abs(std::sqrt(real*real+comp*comp));
2174 double real = eigProb->getSolution().Evals.begin()->realpart;
2175 double comp = eigProb->getSolution().Evals.begin()->imagpart;
2177 return std::abs(std::sqrt(real*real+comp*comp));
2207 double computeSmallestMagEig(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2208 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2210 typedef Thyra::LinearOpBase<double> OP;
2211 typedef Thyra::MultiVectorBase<double> MV;
2213 int startVectors = 1;
2216 const RCP<MV> ivec = Thyra::createMember(A->domain());
2217 Thyra::randomize(-1.0,1.0,ivec.ptr());
2219 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2220 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2222 eigProb->setHermitian(isHermitian);
2225 if(not eigProb->setProblem()) {
2227 return Teuchos::ScalarTraits<double>::nan();
2231 std::string which(
"SM");
2234 Teuchos::ParameterList MyPL;
2235 MyPL.set(
"Verbosity", verbosity );
2236 MyPL.set(
"Which", which );
2237 MyPL.set(
"Block Size", startVectors );
2238 MyPL.set(
"Num Blocks", numBlocks );
2239 MyPL.set(
"Maximum Restarts", restart );
2240 MyPL.set(
"Convergence Tolerance", tol );
2248 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2251 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2253 if(solverreturn==Anasazi::Unconverged) {
2255 return -std::abs(MyBlockKrylovSchur.getRitzValues().begin()->realpart);
2259 return std::abs(eigProb->getSolution().Evals.begin()->realpart);
2271 ModifiableLinearOp getDiagonalOp(
const Teko::LinearOp & A,
const DiagonalType & dt)
2275 return getDiagonalOp(A);
2277 return getLumpedMatrix(A);
2279 return getAbsRowSumMatrix(A);
2282 TEUCHOS_TEST_FOR_EXCEPT(
true);
2285 return Teuchos::null;
2296 ModifiableLinearOp getInvDiagonalOp(
const Teko::LinearOp & A,
const Teko::DiagonalType & dt)
2300 return getInvDiagonalOp(A);
2302 return getInvLumpedMatrix(A);
2304 return getAbsRowSumInvMatrix(A);
2307 TEUCHOS_TEST_FOR_EXCEPT(
true);
2310 return Teuchos::null;
2319 std::string getDiagonalName(
const DiagonalType & dt)
2347 if(name==
"Diagonal")
2351 if(name==
"AbsRowSum")
2359 LinearOp probe(Teuchos::RCP<const Epetra_CrsGraph> &G,
const LinearOp & Op){
2360 #ifdef Teko_ENABLE_Isorropia 2361 Teuchos::ParameterList probeList;
2362 Prober prober(G,probeList,
true);
2363 Teuchos::RCP<Epetra_CrsMatrix> Mat=rcp(
new Epetra_CrsMatrix(Copy,*G));
2365 prober.probe(Mwrap,*Mat);
2366 return Thyra::epetraLinearOp(Mat);
2368 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::runtime_error,
"Probe requires Isorropia");
2372 double norm_1(
const MultiVector & v,std::size_t col)
2374 Teuchos::Array<double> n(v->domain()->dim());
2375 Thyra::norms_1<double>(*v,n);
2380 double norm_2(
const MultiVector & v,std::size_t col)
2382 Teuchos::Array<double> n(v->domain()->dim());
2383 Thyra::norms_2<double>(*v,n);
2388 void putScalar(
const ModifiableLinearOp & op,
double scalar)
2392 RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2395 RCP<Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
2397 eCrsOp->PutScalar(scalar);
2399 catch (std::exception & e) {
2400 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
2402 *out <<
"Teko: putScalar requires an Epetra_CrsMatrix\n";
2403 *out <<
" Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
2405 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
2407 *out <<
"*** THROWN EXCEPTION ***\n";
2408 *out << e.what() << std::endl;
2409 *out <<
"************************\n";
2415 void clipLower(MultiVector & v,
double lowerBound)
2418 using Teuchos::rcp_dynamic_cast;
2424 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2425 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2426 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2428 Teuchos::ArrayRCP<double> values;
2430 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2431 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2432 if(values[j]<lowerBound)
2433 values[j] = lowerBound;
2438 void clipUpper(MultiVector & v,
double upperBound)
2441 using Teuchos::rcp_dynamic_cast;
2446 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2447 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2448 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2450 Teuchos::ArrayRCP<double> values;
2452 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2453 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2454 if(values[j]>upperBound)
2455 values[j] = upperBound;
2460 void replaceValue(MultiVector & v,
double currentValue,
double newValue)
2463 using Teuchos::rcp_dynamic_cast;
2468 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2469 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2470 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2472 Teuchos::ArrayRCP<double> values;
2474 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2475 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2476 if(values[j]==currentValue)
2477 values[j] = newValue;
2482 void columnAverages(
const MultiVector & v,std::vector<double> & averages)
2484 averages.resize(v->domain()->dim());
2487 Thyra::sums<double>(*v,averages);
2490 Thyra::Ordinal rows = v->range()->dim();
2491 for(std::size_t i=0;i<averages.size();i++)
2492 averages[i] = averages[i]/rows;
2495 double average(
const MultiVector & v)
2497 Thyra::Ordinal rows = v->range()->dim();
2498 Thyra::Ordinal cols = v->domain()->dim();
2500 std::vector<double> averages;
2501 columnAverages(v,averages);
2504 for(std::size_t i=0;i<averages.size();i++)
2505 sum += averages[i] * rows;
2507 return sum/(rows*cols);
2510 bool isPhysicallyBlockedLinearOp(
const LinearOp & op)
2513 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2514 if (!pblo.is_null())
2519 Thyra::EOpTransp transp = Thyra::NOTRANS;
2520 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2521 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
2522 pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op);
2523 if (!pblo.is_null())
2529 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > getPhysicallyBlockedLinearOp(
const LinearOp & op, ST *scalar,
bool *transp)
2532 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2533 if(!pblo.is_null()){
2540 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2541 Thyra::EOpTransp eTransp = Thyra::NOTRANS;
2542 Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
2543 pblo = rcp_dynamic_cast<
const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op,
true);
2544 if(!pblo.is_null()){
2546 if(eTransp == Thyra::NOTRANS)
2551 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 .