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)
484 int rows = blockRowCount(blo);
486 TEUCHOS_ASSERT(rows==blockColCount(blo));
488 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
489 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
492 BlockedLinearOp upper = createBlockedOp();
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)
523 int rows = blockRowCount(blo);
525 TEUCHOS_ASSERT(rows==blockColCount(blo));
527 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
528 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
531 BlockedLinearOp lower = createBlockedOp();
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)
580 int rows = blockRowCount(blo);
582 TEUCHOS_ASSERT(rows==blockColCount(blo));
584 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
585 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
588 BlockedLinearOp zeroOp = createBlockedOp();
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)
2468 DiagonalType getDiagonalType(std::string name)
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;
Implements the Epetra_Operator interface with a Thyra LinearOperator. This enables the use of absrtac...