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 auto rowInd =
typename Tpetra::CrsMatrix<ST,LO,GO,NT>::nonconst_global_inds_host_view_type(Kokkos::ViewAllocateWithoutInitializing(
"rowIndices"),stencil.getGlobalMaxNumRowEntries()+1);
238 auto rowData =
typename Tpetra::CrsMatrix<ST,LO,GO,NT>::nonconst_values_host_view_type(Kokkos::ViewAllocateWithoutInitializing(
"rowIndices"),stencil.getGlobalMaxNumRowEntries()+1);
241 for(LO j=0;j< (LO) gl->getNodeNumRows();j++) {
242 GO row = gl->getRowMap()->getGlobalElement(j);
248 stencil.getGlobalRowCopy(row,rowInd,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,rowInd,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 auto rowInd =
typename Tpetra::CrsMatrix<ST,LO,GO,NT>::nonconst_global_inds_host_view_type(Kokkos::ViewAllocateWithoutInitializing(
"rowIndices"),stencil.getGlobalMaxNumRowEntries()+1);
376 auto rowData =
typename Tpetra::CrsMatrix<ST,LO,GO,NT>::nonconst_values_host_view_type(Kokkos::ViewAllocateWithoutInitializing(
"rowIndices"),stencil.getGlobalMaxNumRowEntries()+1);
379 for(LO j=0;j<(LO) gl->getNodeNumRows();j++) {
380 GO row = gl->getRowMap()->getGlobalElement(j);
386 stencil.getGlobalRowCopy(row,rowInd,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,rowInd,rowData);
441 void applyOp(
const LinearOp & A,
const MultiVector & x,MultiVector & y,
double alpha,
double beta)
443 Thyra::apply(*A,Thyra::NOTRANS,*x,y.ptr(),alpha,beta);
461 void applyTransposeOp(
const LinearOp & A,
const MultiVector & x,MultiVector & y,
double alpha,
double beta)
463 Thyra::apply(*A,Thyra::TRANS,*x,y.ptr(),alpha,beta);
468 void update(
double alpha,
const MultiVector & x,
double beta,MultiVector & y)
470 Teuchos::Array<double>
scale;
471 Teuchos::Array<Teuchos::Ptr<const Thyra::MultiVectorBase<double> > > vec;
474 scale.push_back(alpha);
475 vec.push_back(x.ptr());
478 Thyra::linear_combination<double>(scale,vec,beta,y.ptr());
482 BlockedLinearOp getUpperTriBlocks(
const BlockedLinearOp & blo,
bool callEndBlockFill)
488 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
489 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
495 upper->beginBlockFill(rows,rows);
497 for(
int i=0;i<rows;i++) {
501 RCP<const Thyra::LinearOpBase<double> > zed
502 = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
503 upper->setBlock(i,i,zed);
505 for(
int j=i+1;j<rows;j++) {
507 LinearOp uij = blo->getBlock(i,j);
510 if(uij!=Teuchos::null)
511 upper->setBlock(i,j,uij);
515 upper->endBlockFill();
521 BlockedLinearOp getLowerTriBlocks(
const BlockedLinearOp & blo,
bool callEndBlockFill)
527 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
528 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
534 lower->beginBlockFill(rows,rows);
536 for(
int i=0;i<rows;i++) {
540 RCP<const Thyra::LinearOpBase<double> > zed
541 = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
542 lower->setBlock(i,i,zed);
544 for(
int j=0;j<i;j++) {
546 LinearOp uij = blo->getBlock(i,j);
549 if(uij!=Teuchos::null)
550 lower->setBlock(i,j,uij);
554 lower->endBlockFill();
578 BlockedLinearOp zeroBlockedOp(
const BlockedLinearOp & blo)
584 RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
585 RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
591 zeroOp->beginBlockFill(rows,rows);
593 for(
int i=0;i<rows;i++) {
597 RCP<const Thyra::LinearOpBase<double> > zed
598 = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
599 zeroOp->setBlock(i,i,zed);
606 bool isZeroOp(
const LinearOp op)
609 if(op==Teuchos::null)
return true;
612 LinearOp test = rcp_dynamic_cast<const Thyra::ZeroLinearOpBase<double> >(op);
615 if(test!=Teuchos::null)
return true;
619 Thyra::EOpTransp transp = Thyra::NOTRANS;
620 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
621 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
622 test = rcp_dynamic_cast<const Thyra::ZeroLinearOpBase<double> >(wrapped_op);
623 return test!=Teuchos::null;
634 ModifiableLinearOp getAbsRowSumMatrix(
const LinearOp & op)
636 bool isTpetra =
false;
637 RCP<const Epetra_CrsMatrix> eCrsOp;
638 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
642 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
643 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
646 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
648 eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
650 else if (!tOp.is_null()){
651 tCrsOp = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
655 throw std::logic_error(
"Neither Epetra nor Tpetra");
657 catch (std::exception & e) {
658 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
660 *out <<
"Teko: getAbsRowSumMatrix requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
661 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
663 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
665 *out <<
"*** THROWN EXCEPTION ***\n";
666 *out << e.what() << std::endl;
667 *out <<
"************************\n";
674 const RCP<Epetra_Vector> ptrDiag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
675 Epetra_Vector & diag = *ptrDiag;
679 for(
int i=0;i<eCrsOp->NumMyRows();i++) {
682 eCrsOp->ExtractMyRowView(i,numEntries,values);
685 for(
int j=0;j<numEntries;j++)
686 diag[i] += std::abs(values[j]);
690 return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),
"absRowSum( " + op->getObjectLabel() +
" )");
694 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
695 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
699 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
700 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
701 typename Tpetra::CrsMatrix<ST,LO,GO,NT>::local_inds_host_view_type indices;
702 typename Tpetra::CrsMatrix<ST,LO,GO,NT>::values_host_view_type values;
703 tCrsOp->getLocalRowView(i,indices,values);
706 for(LO j=0;j<numEntries;j++)
707 diag.sumIntoLocalValue(i,std::abs(values(j)));
711 return Teko::TpetraHelpers::thyraDiagOp(ptrDiag,*tCrsOp->getRowMap(),
"absRowSum( " + op->getObjectLabel() +
" ))");
725 ModifiableLinearOp getAbsRowSumInvMatrix(
const LinearOp & op)
729 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = rcp_dynamic_cast<const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
730 if(blocked_op != Teuchos::null){
731 int numRows = blocked_op->productRange()->numBlocks();
732 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == numRows);
733 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_diag = Thyra::defaultBlockedLinearOp<double>();
734 blocked_diag->beginBlockFill(numRows,numRows);
735 for(
int r = 0; r < numRows; ++r){
736 for(
int c = 0; c < numRows; ++c){
738 blocked_diag->setNonconstBlock(r,c,getAbsRowSumInvMatrix(blocked_op->getBlock(r,c)));
740 blocked_diag->setBlock(r,c,Thyra::zero<double>(blocked_op->getBlock(r,c)->range(),blocked_op->getBlock(r,c)->domain()));
743 blocked_diag->endBlockFill();
747 if(Teko::TpetraHelpers::isTpetraLinearOp(op)) {
750 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
753 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
754 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
758 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
759 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
760 typename Tpetra::CrsMatrix<ST,LO,GO,NT>::local_inds_host_view_type indices;
761 typename Tpetra::CrsMatrix<ST,LO,GO,NT>::values_host_view_type values;
762 tCrsOp->getLocalRowView(i,indices,values);
765 for(LO j=0;j<numEntries;j++)
766 diag.sumIntoLocalValue(i,std::abs(values(j)));
769 diag.reciprocal(diag);
772 return Teko::TpetraHelpers::thyraDiagOp(ptrDiag,*tCrsOp->getRowMap(),
"absRowSum( " + op->getObjectLabel() +
" ))");
776 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op,
true);
777 RCP<const Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
780 const RCP<Epetra_Vector> ptrDiag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
781 Epetra_Vector & diag = *ptrDiag;
785 for(
int i=0;i<eCrsOp->NumMyRows();i++) {
788 eCrsOp->ExtractMyRowView(i,numEntries,values);
791 for(
int j=0;j<numEntries;j++)
792 diag[i] += std::abs(values[j]);
794 diag.Reciprocal(diag);
797 return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),
"absRowSum( " + op->getObjectLabel() +
" )");
809 ModifiableLinearOp getLumpedMatrix(
const LinearOp & op)
811 RCP<Thyra::VectorBase<ST> > ones = Thyra::createMember(op->domain());
812 RCP<Thyra::VectorBase<ST> > diag = Thyra::createMember(op->range());
815 Thyra::assign(ones.ptr(),1.0);
819 Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
821 return rcp(
new Thyra::DefaultDiagonalLinearOp<ST>(diag));
832 ModifiableLinearOp getInvLumpedMatrix(
const LinearOp & op)
834 RCP<Thyra::VectorBase<ST> > ones = Thyra::createMember(op->domain());
835 RCP<Thyra::VectorBase<ST> > diag = Thyra::createMember(op->range());
838 Thyra::assign(ones.ptr(),1.0);
841 Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
842 Thyra::reciprocal(*diag,diag.ptr());
844 return rcp(
new Thyra::DefaultDiagonalLinearOp<ST>(diag));
858 const ModifiableLinearOp getDiagonalOp(
const LinearOp & op)
860 bool isTpetra =
false;
861 RCP<const Epetra_CrsMatrix> eCrsOp;
862 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
866 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
867 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
870 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
872 eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
874 else if (!tOp.is_null()){
875 tCrsOp = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
879 throw std::logic_error(
"Neither Epetra nor Tpetra");
881 catch (std::exception & e) {
882 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
884 *out <<
"Teko: getDiagonalOp requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
885 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
887 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
889 *out <<
"*** THROWN EXCEPTION ***\n";
890 *out << e.what() << std::endl;
891 *out <<
"************************\n";
898 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
899 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
902 return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
906 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
907 tCrsOp->getLocalDiagCopy(*diag);
910 return Teko::TpetraHelpers::thyraDiagOp(diag,*tCrsOp->getRowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
915 const MultiVector getDiagonal(
const LinearOp & op)
917 bool isTpetra =
false;
918 RCP<const Epetra_CrsMatrix> eCrsOp;
919 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp;
923 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
924 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
927 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
929 eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
931 else if (!tOp.is_null()){
932 tCrsOp = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
936 throw std::logic_error(
"Neither Epetra nor Tpetra");
938 catch (std::exception & e) {
939 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
941 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op);
942 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
946 *out <<
"Teko: getDiagonal requires an Epetra_CrsMatrix or a Tpetra::CrsMatrix\n";
947 *out <<
" Could not extract an Epetra_Operator or a Tpetra_Operator from a \"" << op->description() << std::endl;
949 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix or a Tpetra_Operator to a Tpetra::CrsMatrix\n";
951 *out <<
"*** THROWN EXCEPTION ***\n";
952 *out << e.what() << std::endl;
953 *out <<
"************************\n";
960 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
961 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
963 return Thyra::create_Vector(diag,Thyra::create_VectorSpace(Teuchos::rcpFromRef(eCrsOp->RowMap())));
967 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
968 tCrsOp->getLocalDiagCopy(*diag);
971 return Thyra::createVector<ST,LO,GO,NT>(diag,Thyra::createVectorSpace<ST,LO,GO,NT>(tCrsOp->getRowMap()));
976 const MultiVector getDiagonal(
const Teko::LinearOp & A,
const DiagonalType & dt)
978 LinearOp diagOp = Teko::getDiagonalOp(A,dt);
980 Teuchos::RCP<const Thyra::MultiVectorBase<double> > v =
981 Teuchos::rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<double> >(diagOp)->getDiag();
982 return Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(v);
996 const ModifiableLinearOp getInvDiagonalOp(
const LinearOp & op)
999 auto diagonal_op = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<double>>(op);
1000 if(diagonal_op != Teuchos::null){
1001 auto diag = diagonal_op->getDiag();
1002 auto inv_diag = diag->clone_v();
1003 Thyra::reciprocal(*diag,inv_diag.ptr());
1004 return rcp(
new Thyra::DefaultDiagonalLinearOp<double>(inv_diag));
1008 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = rcp_dynamic_cast<const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
1009 if(blocked_op != Teuchos::null){
1010 int numRows = blocked_op->productRange()->numBlocks();
1011 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == numRows);
1012 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_diag = Thyra::defaultBlockedLinearOp<double>();
1013 blocked_diag->beginBlockFill(numRows,numRows);
1014 for(
int r = 0; r < numRows; ++r){
1015 for(
int c = 0; c < numRows; ++c){
1017 blocked_diag->setNonconstBlock(r,c,getInvDiagonalOp(blocked_op->getBlock(r,c)));
1019 blocked_diag->setBlock(r,c,Thyra::zero<double>(blocked_op->getBlock(r,c)->range(),blocked_op->getBlock(r,c)->domain()));
1022 blocked_diag->endBlockFill();
1023 return blocked_diag;
1026 if (Teko::TpetraHelpers::isTpetraLinearOp(op)){
1028 bool transp =
false;
1029 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
1032 const RCP<Tpetra::Vector<ST,LO,GO,NT> > diag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
1033 diag->scale(scalar);
1034 tCrsOp->getLocalDiagCopy(*diag);
1035 diag->reciprocal(*diag);
1038 return Teko::TpetraHelpers::thyraDiagOp(diag,*tCrsOp->getRowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
1042 RCP<const Thyra::EpetraLinearOp > eOp = rcp_dynamic_cast<const Thyra::EpetraLinearOp >(op,
true);
1043 RCP<const Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp->epetra_op(),
true);
1046 const RCP<Epetra_Vector> diag = rcp(
new Epetra_Vector(eCrsOp->RowMap()));
1047 TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
1048 diag->Reciprocal(*diag);
1051 return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),
"inv(diag( " + op->getObjectLabel() +
" ))");
1067 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opm,
const LinearOp & opr)
1072 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1073 bool isBlockedM = isPhysicallyBlockedLinearOp(opm);
1074 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1077 if((isBlockedL && isBlockedM && isBlockedR)){
1079 double scalarl = 0.0;
1080 bool transpl =
false;
1081 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1082 double scalarm = 0.0;
1083 bool transpm =
false;
1084 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opm = getPhysicallyBlockedLinearOp(opm,&scalarm,&transpm);
1085 double scalarr = 0.0;
1086 bool transpr =
false;
1087 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1088 double scalar = scalarl*scalarm*scalarr;
1090 int numRows = blocked_opl->productRange()->numBlocks();
1091 int numCols = blocked_opr->productDomain()->numBlocks();
1092 int numMiddle = blocked_opm->productRange()->numBlocks();
1095 TEUCHOS_ASSERT(blocked_opm->productDomain()->numBlocks() == numMiddle);
1096 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1097 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1099 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1100 blocked_product->beginBlockFill(numRows,numCols);
1101 for(
int r = 0; r < numRows; ++r){
1102 for(
int c = 0; c < numCols; ++c){
1103 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opm->getBlock(0,0),blocked_opr->getBlock(0,c));
1104 for(
int m = 1; m < numMiddle; ++m){
1105 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opm->getBlock(m,m),blocked_opr->getBlock(m,c));
1106 product_rc = explicitAdd(product_rc,product_m);
1108 blocked_product->setBlock(r,c,product_rc);
1111 blocked_product->endBlockFill();
1112 return Thyra::scale<double>(scalar,blocked_product.getConst());
1116 if(isBlockedL && !isBlockedM && isBlockedR){
1117 double scalarl = 0.0;
1118 bool transpl =
false;
1119 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1120 double scalarr = 0.0;
1121 bool transpr =
false;
1122 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1123 double scalar = scalarl*scalarr;
1125 int numRows = blocked_opl->productRange()->numBlocks();
1126 int numCols = blocked_opr->productDomain()->numBlocks();
1130 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1131 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1133 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1134 blocked_product->beginBlockFill(numRows,numCols);
1135 for(
int r = 0; r < numRows; ++r){
1136 for(
int c = 0; c < numCols; ++c){
1137 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),opm,blocked_opr->getBlock(0,c));
1138 blocked_product->setBlock(r,c,product_rc);
1141 blocked_product->endBlockFill();
1142 return Thyra::scale<double>(scalar,blocked_product.getConst());
1146 if(!isBlockedL && !isBlockedM && isBlockedR){
1147 double scalarr = 0.0;
1148 bool transpr =
false;
1149 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1150 double scalar = scalarr;
1153 int numCols = blocked_opr->productDomain()->numBlocks();
1157 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1159 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1160 blocked_product->beginBlockFill(numRows,numCols);
1161 for(
int c = 0; c < numCols; ++c){
1162 LinearOp product_c = explicitMultiply(opl,opm,blocked_opr->getBlock(0,c));
1163 blocked_product->setBlock(0,c,product_c);
1165 blocked_product->endBlockFill();
1166 return Thyra::scale<double>(scalar,blocked_product.getConst());
1171 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1172 bool isTpetram = Teko::TpetraHelpers::isTpetraLinearOp(opm);
1173 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1175 if(isTpetral && isTpetram && isTpetrar){
1179 bool transpl =
false;
1180 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1182 bool transpm =
false;
1183 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpm = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarm, &transpm);
1185 bool transpr =
false;
1186 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1189 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1190 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1193 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1194 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1195 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1196 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1197 explicitCrsOp->resumeFill();
1198 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1199 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1200 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1203 }
else if (isTpetral && !isTpetram && isTpetrar){
1207 bool transpl =
false;
1208 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1210 bool transpr =
false;
1211 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1213 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1216 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<ST> >(opm);
1217 if(dOpm != Teuchos::null){
1218 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1219 diagPtr = rcp_dynamic_cast<const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1222 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opm) != Teuchos::null){
1223 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpl->getDomainMap()));
1226 TEUCHOS_ASSERT(
false);
1228 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()));
1231 tCrsOplm->rightScale(*diagPtr);
1234 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1235 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1238 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1239 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1240 explicitCrsOp->resumeFill();
1241 explicitCrsOp->scale(scalarl*scalarr);
1242 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1243 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1249 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1252 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1253 Thyra::epetraExtDiagScaledMatProdTransformer();
1256 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1257 prodTrans->transform(*implicitOp,explicitOp.ptr());
1258 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1259 " * " + opm->getObjectLabel() +
1260 " * " + opr->getObjectLabel() +
" )");
1281 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opm,
const LinearOp & opr,
1282 const ModifiableLinearOp & destOp)
1284 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1285 bool isTpetram = Teko::TpetraHelpers::isTpetraLinearOp(opm);
1286 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1288 if(isTpetral && isTpetram && isTpetrar){
1292 bool transpl =
false;
1293 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1295 bool transpm =
false;
1296 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpm = Teko::TpetraHelpers::getTpetraCrsMatrix(opm, &scalarm, &transpm);
1298 bool transpr =
false;
1299 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1302 auto tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(destOp);
1303 if(tExplicitOp.is_null())
1304 tExplicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1307 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOplm = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1308 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1309 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpm,transpm,*tCrsOplm);
1310 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1311 explicitCrsOp->resumeFill();
1312 explicitCrsOp->scale(scalarl*scalarm*scalarr);
1313 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1314 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1317 }
else if (isTpetral && !isTpetram && isTpetrar){
1321 bool transpl =
false;
1322 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1324 bool transpr =
false;
1325 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1328 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpm = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<ST> >(opm,
true);
1329 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpm->getDiag(),
true);
1330 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1331 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()));
1334 tCrsOplm->rightScale(*diagPtr);
1337 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1338 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1341 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1342 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOplm,
false,*tCrsOpr,transpr,*explicitCrsOp);
1343 explicitCrsOp->resumeFill();
1344 explicitCrsOp->scale(scalarl*scalarr);
1345 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1346 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1352 const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
1355 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1356 Thyra::epetraExtDiagScaledMatProdTransformer();
1359 ModifiableLinearOp explicitOp;
1362 if(destOp==Teuchos::null)
1363 explicitOp = prodTrans->createOutputOp();
1365 explicitOp = destOp;
1368 prodTrans->transform(*implicitOp,explicitOp.ptr());
1371 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1372 " * " + opm->getObjectLabel() +
1373 " * " + opr->getObjectLabel() +
" )");
1390 const LinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr)
1395 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1396 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1399 if((isBlockedL && isBlockedR)){
1400 double scalarl = 0.0;
1401 bool transpl =
false;
1402 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1403 double scalarr = 0.0;
1404 bool transpr =
false;
1405 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1406 double scalar = scalarl*scalarr;
1408 int numRows = blocked_opl->productRange()->numBlocks();
1409 int numCols = blocked_opr->productDomain()->numBlocks();
1410 int numMiddle = blocked_opl->productDomain()->numBlocks();
1412 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1414 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1415 blocked_product->beginBlockFill(numRows,numCols);
1416 for(
int r = 0; r < numRows; ++r){
1417 for(
int c = 0; c < numCols; ++c){
1418 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1419 for(
int m = 1; m < numMiddle; ++m){
1420 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1421 product_rc = explicitAdd(product_rc,product_m);
1423 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1426 blocked_product->endBlockFill();
1427 return blocked_product;
1431 if((isBlockedL && !isBlockedR)){
1432 double scalarl = 0.0;
1433 bool transpl =
false;
1434 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1435 double scalar = scalarl;
1437 int numRows = blocked_opl->productRange()->numBlocks();
1441 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1443 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1444 blocked_product->beginBlockFill(numRows,numCols);
1445 for(
int r = 0; r < numRows; ++r){
1446 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1447 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1449 blocked_product->endBlockFill();
1450 return blocked_product;
1454 if((!isBlockedL && isBlockedR)){
1455 double scalarr = 0.0;
1456 bool transpr =
false;
1457 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1458 double scalar = scalarr;
1461 int numCols = blocked_opr->productDomain()->numBlocks();
1464 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1466 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1467 blocked_product->beginBlockFill(numRows,numCols);
1468 for(
int c = 0; c < numCols; ++c){
1469 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1470 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1472 blocked_product->endBlockFill();
1473 return blocked_product;
1476 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1477 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1479 if(isTpetral && isTpetrar){
1482 bool transpl =
false;
1483 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1485 bool transpr =
false;
1486 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1489 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1490 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1493 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1494 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1495 explicitCrsOp->resumeFill();
1496 explicitCrsOp->scale(scalarl*scalarr);
1497 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1498 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1501 }
else if (isTpetral && !isTpetrar){
1505 bool transpl =
false;
1506 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1509 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<ST> >(opr,
true);
1510 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1511 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1512 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()));
1514 explicitCrsOp->rightScale(*diagPtr);
1515 explicitCrsOp->resumeFill();
1516 explicitCrsOp->scale(scalarl);
1517 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1519 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 }
else if (!isTpetral && isTpetrar){
1525 bool transpr =
false;
1526 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1528 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr;
1531 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<ST> >(opl);
1532 if(dOpl != Teuchos::null){
1533 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1534 diagPtr = rcp_dynamic_cast<const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1537 else if(rcp_dynamic_cast<
const Thyra::ZeroLinearOpBase<ST> >(opl) != Teuchos::null){
1538 diagPtr = rcp(
new Tpetra::Vector<ST,LO,GO,NT>(tCrsOpr->getRangeMap()));
1541 TEUCHOS_ASSERT(
false);
1543 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()));
1545 explicitCrsOp->leftScale(*diagPtr);
1546 explicitCrsOp->resumeFill();
1547 explicitCrsOp->scale(scalarr);
1548 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1550 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1555 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1558 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1559 = Thyra::epetraExtDiagScalingTransformer();
1563 if(not prodTrans->isCompatible(*implicitOp))
1564 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1567 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1568 prodTrans->transform(*implicitOp,explicitOp.ptr());
1569 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1570 " * " + opr->getObjectLabel() +
" )");
1589 const ModifiableLinearOp explicitMultiply(
const LinearOp & opl,
const LinearOp & opr,
1590 const ModifiableLinearOp & destOp)
1595 bool isBlockedL = isPhysicallyBlockedLinearOp(opl);
1596 bool isBlockedR = isPhysicallyBlockedLinearOp(opr);
1599 if((isBlockedL && isBlockedR)){
1600 double scalarl = 0.0;
1601 bool transpl =
false;
1602 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1603 double scalarr = 0.0;
1604 bool transpr =
false;
1605 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1606 double scalar = scalarl*scalarr;
1608 int numRows = blocked_opl->productRange()->numBlocks();
1609 int numCols = blocked_opr->productDomain()->numBlocks();
1610 int numMiddle = blocked_opl->productDomain()->numBlocks();
1612 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1614 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1615 blocked_product->beginBlockFill(numRows,numCols);
1616 for(
int r = 0; r < numRows; ++r){
1617 for(
int c = 0; c < numCols; ++c){
1619 LinearOp product_rc = explicitMultiply(blocked_opl->getBlock(r,0),blocked_opr->getBlock(0,c));
1620 for(
int m = 1; m < numMiddle; ++m){
1621 LinearOp product_m = explicitMultiply(blocked_opl->getBlock(r,m),blocked_opr->getBlock(m,c));
1622 product_rc = explicitAdd(product_rc,product_m);
1624 blocked_product->setBlock(r,c,Thyra::scale(scalar,product_rc));
1627 blocked_product->endBlockFill();
1628 return blocked_product;
1632 if((isBlockedL && !isBlockedR)){
1633 double scalarl = 0.0;
1634 bool transpl =
false;
1635 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl,&scalarl,&transpl);
1636 double scalar = scalarl;
1638 int numRows = blocked_opl->productRange()->numBlocks();
1642 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == numMiddle);
1644 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1645 blocked_product->beginBlockFill(numRows,numCols);
1646 for(
int r = 0; r < numRows; ++r){
1647 LinearOp product_r = explicitMultiply(blocked_opl->getBlock(r,0),opr);
1648 blocked_product->setBlock(r,0,Thyra::scale(scalar,product_r));
1650 blocked_product->endBlockFill();
1651 return blocked_product;
1655 if((!isBlockedL && isBlockedR)){
1656 double scalarr = 0.0;
1657 bool transpr =
false;
1658 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr,&scalarr,&transpr);
1659 double scalar = scalarr;
1662 int numCols = blocked_opr->productDomain()->numBlocks();
1665 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numMiddle);
1667 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_product = Thyra::defaultBlockedLinearOp<double>();
1668 blocked_product->beginBlockFill(numRows,numCols);
1669 for(
int c = 0; c < numCols; ++c){
1670 LinearOp product_c = explicitMultiply(opl,blocked_opr->getBlock(0,c));
1671 blocked_product->setBlock(0,c,Thyra::scale(scalar,product_c));
1673 blocked_product->endBlockFill();
1674 return blocked_product;
1677 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1678 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1680 if(isTpetral && isTpetrar){
1684 bool transpl =
false;
1685 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1687 bool transpr =
false;
1688 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1691 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1692 if(destOp!=Teuchos::null)
1693 explicitOp = destOp;
1695 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1696 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1699 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::createCrsMatrix<ST,LO,GO,NT>(tCrsOpl->getRowMap());
1700 Tpetra::MatrixMatrix::Multiply<ST,LO,GO,NT>(*tCrsOpl,transpl,*tCrsOpr,transpr,*explicitCrsOp);
1701 explicitCrsOp->resumeFill();
1702 explicitCrsOp->scale(scalarl*scalarr);
1703 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpl->getRangeMap());
1704 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1707 }
else if (isTpetral && !isTpetrar){
1711 bool transpl =
false;
1712 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1715 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpr = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<ST> >(opr);
1716 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpr->getDiag(),
true);
1717 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1720 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()));
1721 explicitCrsOp->rightScale(*diagPtr);
1722 explicitCrsOp->resumeFill();
1723 explicitCrsOp->scale(scalarl);
1724 explicitCrsOp->fillComplete(tCrsOpl->getDomainMap(),tCrsOpl->getRangeMap());
1725 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1727 }
else if (!isTpetral && isTpetrar){
1731 bool transpr =
false;
1732 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1735 RCP<const Thyra::DiagonalLinearOpBase<ST> > dOpl = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<ST> >(opl,
true);
1736 RCP<const Thyra::TpetraVector<ST,LO,GO,NT> > tPtr = rcp_dynamic_cast<const Thyra::TpetraVector<ST,LO,GO,NT> >(dOpl->getDiag(),
true);
1737 RCP<const Tpetra::Vector<ST,LO,GO,NT> > diagPtr = rcp_dynamic_cast<const Tpetra::Vector<ST,LO,GO,NT> >(tPtr->getConstTpetraVector(),
true);
1740 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()));
1741 explicitCrsOp->leftScale(*diagPtr);
1742 explicitCrsOp->resumeFill();
1743 explicitCrsOp->scale(scalarr);
1744 explicitCrsOp->fillComplete(tCrsOpr->getDomainMap(),tCrsOpr->getRangeMap());
1745 return Thyra::tpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1750 const LinearOp implicitOp = Thyra::multiply(opl,opr);
1754 RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
1755 = Thyra::epetraExtDiagScalingTransformer();
1759 if(not prodTrans->isCompatible(*implicitOp))
1760 prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
1763 ModifiableLinearOp explicitOp;
1766 if(destOp==Teuchos::null)
1767 explicitOp = prodTrans->createOutputOp();
1769 explicitOp = destOp;
1772 prodTrans->transform(*implicitOp,explicitOp.ptr());
1775 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1776 " * " + opr->getObjectLabel() +
" )");
1792 const LinearOp explicitAdd(
const LinearOp & opl_in,
const LinearOp & opr_in)
1795 if(isPhysicallyBlockedLinearOp(opl_in) && isPhysicallyBlockedLinearOp(opr_in)){
1796 double scalarl = 0.0;
1797 bool transpl =
false;
1798 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl_in, &scalarl, &transpl);
1800 double scalarr = 0.0;
1801 bool transpr =
false;
1802 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr_in, &scalarr, &transpr);
1804 int numRows = blocked_opl->productRange()->numBlocks();
1805 int numCols = blocked_opl->productDomain()->numBlocks();
1806 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1807 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1809 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1810 blocked_sum->beginBlockFill(numRows,numCols);
1811 for(
int r = 0; r < numRows; ++r)
1812 for(
int c = 0; c < numCols; ++c)
1813 blocked_sum->setBlock(r,c,explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c))));
1814 blocked_sum->endBlockFill();
1819 LinearOp opl = opl_in;
1820 LinearOp opr = opr_in;
1821 if(isPhysicallyBlockedLinearOp(opl_in)){
1822 double scalarl = 0.0;
1823 bool transpl =
false;
1824 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl_in, &scalarl, &transpl);
1825 TEUCHOS_ASSERT(blocked_opl->productRange()->numBlocks() == 1);
1826 TEUCHOS_ASSERT(blocked_opl->productDomain()->numBlocks() == 1);
1827 opl = Thyra::scale(scalarl,blocked_opl->getBlock(0,0));
1829 if(isPhysicallyBlockedLinearOp(opr_in)){
1830 double scalarr = 0.0;
1831 bool transpr =
false;
1832 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr_in, &scalarr, &transpr);
1833 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == 1);
1834 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == 1);
1835 opr = Thyra::scale(scalarr,blocked_opr->getBlock(0,0));
1838 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1839 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1847 bool transp =
false;
1848 auto crs_op = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalar, &transp);
1849 auto zero_crs = Tpetra::createCrsMatrix<ST,LO,GO,NT>(crs_op->getRowMap());
1850 zero_crs->fillComplete();
1851 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);
1854 return opr->clone();
1859 bool transp =
false;
1860 auto crs_op = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalar, &transp);
1861 auto zero_crs = Tpetra::createCrsMatrix<ST,LO,GO,NT>(crs_op->getRowMap());
1862 zero_crs->fillComplete();
1863 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);
1866 return opl->clone();
1869 if(isTpetral && isTpetrar){
1873 bool transpl =
false;
1874 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1876 bool transpr =
false;
1877 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1880 RCP<Thyra::LinearOpBase<ST> > explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1881 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1884 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1885 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1890 const LinearOp implicitOp = Thyra::add(opl,opr);
1893 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1894 Thyra::epetraExtAddTransformer();
1897 const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
1898 prodTrans->transform(*implicitOp,explicitOp.ptr());
1899 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
1900 " + " + opr->getObjectLabel() +
" )");
1918 const ModifiableLinearOp explicitAdd(
const LinearOp & opl,
const LinearOp & opr,
1919 const ModifiableLinearOp & destOp)
1922 if(isPhysicallyBlockedLinearOp(opl)){
1923 TEUCHOS_ASSERT(isPhysicallyBlockedLinearOp(opr));
1925 double scalarl = 0.0;
1926 bool transpl =
false;
1927 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opl = getPhysicallyBlockedLinearOp(opl, &scalarl, &transpl);
1929 double scalarr = 0.0;
1930 bool transpr =
false;
1931 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_opr = getPhysicallyBlockedLinearOp(opr, &scalarr, &transpr);
1933 int numRows = blocked_opl->productRange()->numBlocks();
1934 int numCols = blocked_opl->productDomain()->numBlocks();
1935 TEUCHOS_ASSERT(blocked_opr->productRange()->numBlocks() == numRows);
1936 TEUCHOS_ASSERT(blocked_opr->productDomain()->numBlocks() == numCols);
1938 RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_sum = Teuchos::rcp_dynamic_cast<Thyra::DefaultBlockedLinearOp<double>>(destOp);
1939 if(blocked_sum.is_null()) {
1941 blocked_sum = Thyra::defaultBlockedLinearOp<double>();
1943 blocked_sum->beginBlockFill(numRows,numCols);
1944 for(
int r = 0; r < numRows; ++r) {
1945 for(
int c = 0; c < numCols; ++c) {
1946 auto block = explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c)),Teuchos::null);
1947 blocked_sum->setNonconstBlock(r,c,block);
1950 blocked_sum->endBlockFill();
1955 for(
int r = 0; r < numRows; ++r)
1956 for(
int c = 0; c < numCols; ++c)
1957 explicitAdd(Thyra::scale(scalarl,blocked_opl->getBlock(r,c)),Thyra::scale(scalarr,blocked_opr->getBlock(r,c)),blocked_sum->getNonconstBlock(r,c));
1963 bool isTpetral = Teko::TpetraHelpers::isTpetraLinearOp(opl);
1964 bool isTpetrar = Teko::TpetraHelpers::isTpetraLinearOp(opr);
1966 if(isTpetral && isTpetrar){
1970 bool transpl =
false;
1971 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpl = Teko::TpetraHelpers::getTpetraCrsMatrix(opl, &scalarl, &transpl);
1973 bool transpr =
false;
1974 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOpr = Teko::TpetraHelpers::getTpetraCrsMatrix(opr, &scalarr, &transpr);
1977 RCP<Thyra::LinearOpBase<ST> > explicitOp;
1978 if(destOp!=Teuchos::null)
1979 explicitOp = destOp;
1981 explicitOp = rcp(
new Thyra::TpetraLinearOp<ST,LO,GO,NT>());
1982 RCP<Thyra::TpetraLinearOp<ST,LO,GO,NT> > tExplicitOp = rcp_dynamic_cast<Thyra::TpetraLinearOp<ST,LO,GO,NT> >(explicitOp);
1985 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > explicitCrsOp = Tpetra::MatrixMatrix::add<ST,LO,GO,NT>(scalarl,transpl,*tCrsOpl,scalarr,transpr,*tCrsOpr);
1986 tExplicitOp->initialize(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(explicitCrsOp->getDomainMap()),explicitCrsOp);
1992 const LinearOp implicitOp = Thyra::add(opl,opr);
1995 const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
1996 Thyra::epetraExtAddTransformer();
1999 RCP<Thyra::LinearOpBase<double> > explicitOp;
2000 if(destOp!=Teuchos::null)
2001 explicitOp = destOp;
2003 explicitOp = prodTrans->createOutputOp();
2006 prodTrans->transform(*implicitOp,explicitOp.ptr());
2007 explicitOp->setObjectLabel(
"explicit( " + opl->getObjectLabel() +
2008 " + " + opr->getObjectLabel() +
" )");
2018 const ModifiableLinearOp explicitSum(
const LinearOp & op,
2019 const ModifiableLinearOp & destOp)
2022 const RCP<const Epetra_CrsMatrix> epetraOp =
2023 rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*op),
true);
2025 if(destOp==Teuchos::null) {
2026 Teuchos::RCP<Epetra_Operator> epetraDest = Teuchos::rcp(
new Epetra_CrsMatrix(*epetraOp));
2028 return Thyra::nonconstEpetraLinearOp(epetraDest);
2031 const RCP<Epetra_CrsMatrix> epetraDest =
2032 rcp_dynamic_cast<Epetra_CrsMatrix>(get_Epetra_Operator(*destOp),
true);
2034 EpetraExt::MatrixMatrix::Add(*epetraOp,
false,1.0,*epetraDest,1.0);
2039 const LinearOp explicitTranspose(
const LinearOp & op)
2041 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2043 RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op,
true);
2044 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
2046 Tpetra::RowMatrixTransposer<ST,LO,GO,NT> transposer(tCrsOp);
2047 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > transOp = transposer.createTranspose();
2049 return Thyra::constTpetraLinearOp<ST,LO,GO,NT>(Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getRangeMap()),Thyra::tpetraVectorSpace<ST,LO,GO,NT>(transOp->getDomainMap()),transOp);
2053 RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2054 TEUCHOS_TEST_FOR_EXCEPTION(eOp==Teuchos::null,std::logic_error,
2055 "Teko::explicitTranspose Not an Epetra_Operator");
2056 RCP<const Epetra_RowMatrix> eRowMatrixOp
2057 = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(eOp);
2058 TEUCHOS_TEST_FOR_EXCEPTION(eRowMatrixOp==Teuchos::null,std::logic_error,
2059 "Teko::explicitTranspose Not an Epetra_RowMatrix");
2062 EpetraExt::RowMatrix_Transpose tranposeOp;
2063 Epetra_RowMatrix & eMat = tranposeOp(
const_cast<Epetra_RowMatrix &
>(*eRowMatrixOp));
2067 Teuchos::RCP<Epetra_CrsMatrix> crsMat
2068 = Teuchos::rcp(
new Epetra_CrsMatrix(
dynamic_cast<Epetra_CrsMatrix &
>(eMat)));
2070 return Thyra::epetraLinearOp(crsMat);
2074 double frobeniusNorm(
const LinearOp & op_in)
2077 double scalar = 1.0;
2080 if(isPhysicallyBlockedLinearOp(op_in)){
2081 bool transp =
false;
2082 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > blocked_op = getPhysicallyBlockedLinearOp(op_in,&scalar,&transp);
2083 TEUCHOS_ASSERT(blocked_op->productRange()->numBlocks() == 1);
2084 TEUCHOS_ASSERT(blocked_op->productDomain()->numBlocks() == 1);
2085 op = blocked_op->getBlock(0,0);
2089 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2090 const RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
2091 const RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > crsOp = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),
true);
2092 return crsOp->getFrobeniusNorm();
2094 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2095 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(epOp,
true);
2096 return crsOp->NormFrobenius();
2100 double oneNorm(
const LinearOp & op)
2102 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2103 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"One norm not currently implemented for Tpetra matrices");
2106 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2107 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(epOp,
true);
2108 return crsOp->NormOne();
2112 double infNorm(
const LinearOp & op)
2114 if(Teko::TpetraHelpers::isTpetraLinearOp(op)){
2116 bool transp =
false;
2117 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > tCrsOp = Teko::TpetraHelpers::getTpetraCrsMatrix(op, &scalar, &transp);
2120 const RCP<Tpetra::Vector<ST,LO,GO,NT> > ptrDiag = Tpetra::createVector<ST,LO,GO,NT>(tCrsOp->getRowMap());
2121 Tpetra::Vector<ST,LO,GO,NT> & diag = *ptrDiag;
2124 diag.putScalar(0.0);
2125 for(LO i=0;i<(LO) tCrsOp->getNodeNumRows();i++) {
2126 LO numEntries = tCrsOp->getNumEntriesInLocalRow (i);
2127 typename Tpetra::CrsMatrix<ST,LO,GO,NT>::local_inds_host_view_type indices;
2128 typename Tpetra::CrsMatrix<ST,LO,GO,NT>::values_host_view_type values;
2129 tCrsOp->getLocalRowView(i,indices,values);
2132 for(LO j=0;j<numEntries;j++)
2133 diag.sumIntoLocalValue(i,std::abs(values(j)));
2135 return diag.normInf()*scalar;
2138 const RCP<const Epetra_Operator> epOp = Thyra::get_Epetra_Operator(*op);
2139 const RCP<const Epetra_CrsMatrix> crsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(epOp,
true);
2140 return crsOp->NormInf();
2144 const LinearOp buildDiagonal(
const MultiVector & src,
const std::string & lbl)
2146 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(src->range());
2147 Thyra::copy(*src->col(0),dst.ptr());
2149 return Thyra::diagonal<double>(dst,lbl);
2152 const LinearOp buildInvDiagonal(
const MultiVector & src,
const std::string & lbl)
2154 const RCP<const Thyra::VectorBase<double> > srcV = src->col(0);
2155 RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(srcV->range());
2156 Thyra::reciprocal<double>(*srcV,dst.ptr());
2158 return Thyra::diagonal<double>(dst,lbl);
2162 BlockedMultiVector buildBlockedMultiVector(
const std::vector<MultiVector> & mvv)
2164 Teuchos::Array<MultiVector> mvA;
2165 Teuchos::Array<VectorSpace> vsA;
2168 std::vector<MultiVector>::const_iterator itr;
2169 for(itr=mvv.begin();itr!=mvv.end();++itr) {
2170 mvA.push_back(*itr);
2171 vsA.push_back((*itr)->range());
2175 const RCP<const Thyra::DefaultProductVectorSpace<double> > vs
2176 = Thyra::productVectorSpace<double>(vsA);
2178 return Thyra::defaultProductMultiVector<double>(vs,mvA);
2191 Teuchos::RCP<Thyra::VectorBase<double> > indicatorVector(
2192 const std::vector<int> & indices,
2193 const VectorSpace & vs,
2194 double onValue,
double offValue)
2200 RCP<Thyra::VectorBase<double> > v = Thyra::createMember<double>(vs);
2201 Thyra::put_scalar<double>(offValue,v.ptr());
2204 for(std::size_t i=0;i<indices.size();i++)
2205 Thyra::set_ele<double>(indices[i],onValue,v.ptr());
2234 double computeSpectralRad(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2235 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2237 typedef Thyra::LinearOpBase<double> OP;
2238 typedef Thyra::MultiVectorBase<double> MV;
2240 int startVectors = 1;
2243 const RCP<MV> ivec = Thyra::createMember(A->domain());
2244 Thyra::randomize(-1.0,1.0,ivec.ptr());
2246 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2247 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2249 eigProb->setHermitian(isHermitian);
2252 if(not eigProb->setProblem()) {
2254 return Teuchos::ScalarTraits<double>::nan();
2258 std::string which(
"LM");
2262 Teuchos::ParameterList MyPL;
2263 MyPL.set(
"Verbosity", verbosity );
2264 MyPL.set(
"Which", which );
2265 MyPL.set(
"Block Size", startVectors );
2266 MyPL.set(
"Num Blocks", numBlocks );
2267 MyPL.set(
"Maximum Restarts", restart );
2268 MyPL.set(
"Convergence Tolerance", tol );
2276 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2279 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2281 if(solverreturn==Anasazi::Unconverged) {
2282 double real = MyBlockKrylovSchur.getRitzValues().begin()->realpart;
2283 double comp = MyBlockKrylovSchur.getRitzValues().begin()->imagpart;
2285 return -std::abs(std::sqrt(real*real+comp*comp));
2291 double real = eigProb->getSolution().Evals.begin()->realpart;
2292 double comp = eigProb->getSolution().Evals.begin()->imagpart;
2294 return std::abs(std::sqrt(real*real+comp*comp));
2324 double computeSmallestMagEig(
const RCP<
const Thyra::LinearOpBase<double> > & A,
double tol,
2325 bool isHermitian,
int numBlocks,
int restart,
int verbosity)
2327 typedef Thyra::LinearOpBase<double> OP;
2328 typedef Thyra::MultiVectorBase<double> MV;
2330 int startVectors = 1;
2333 const RCP<MV> ivec = Thyra::createMember(A->domain());
2334 Thyra::randomize(-1.0,1.0,ivec.ptr());
2336 RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
2337 = rcp(
new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
2339 eigProb->setHermitian(isHermitian);
2342 if(not eigProb->setProblem()) {
2344 return Teuchos::ScalarTraits<double>::nan();
2348 std::string which(
"SM");
2351 Teuchos::ParameterList MyPL;
2352 MyPL.set(
"Verbosity", verbosity );
2353 MyPL.set(
"Which", which );
2354 MyPL.set(
"Block Size", startVectors );
2355 MyPL.set(
"Num Blocks", numBlocks );
2356 MyPL.set(
"Maximum Restarts", restart );
2357 MyPL.set(
"Convergence Tolerance", tol );
2365 Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
2368 Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
2370 if(solverreturn==Anasazi::Unconverged) {
2372 return -std::abs(MyBlockKrylovSchur.getRitzValues().begin()->realpart);
2376 return std::abs(eigProb->getSolution().Evals.begin()->realpart);
2388 ModifiableLinearOp getDiagonalOp(
const Teko::LinearOp & A,
const DiagonalType & dt)
2392 return getDiagonalOp(A);
2394 return getLumpedMatrix(A);
2396 return getAbsRowSumMatrix(A);
2399 TEUCHOS_TEST_FOR_EXCEPT(
true);
2402 return Teuchos::null;
2413 ModifiableLinearOp getInvDiagonalOp(
const Teko::LinearOp & A,
const Teko::DiagonalType & dt)
2417 return getInvDiagonalOp(A);
2419 return getInvLumpedMatrix(A);
2421 return getAbsRowSumInvMatrix(A);
2424 TEUCHOS_TEST_FOR_EXCEPT(
true);
2427 return Teuchos::null;
2436 std::string getDiagonalName(
const DiagonalType & dt)
2464 if(name==
"Diagonal")
2468 if(name==
"AbsRowSum")
2476 LinearOp probe(Teuchos::RCP<const Epetra_CrsGraph> &G,
const LinearOp & Op){
2477 #ifdef Teko_ENABLE_Isorropia
2478 Teuchos::ParameterList probeList;
2479 Prober prober(G,probeList,
true);
2480 Teuchos::RCP<Epetra_CrsMatrix> Mat=rcp(
new Epetra_CrsMatrix(Copy,*G));
2482 prober.probe(Mwrap,*Mat);
2483 return Thyra::epetraLinearOp(Mat);
2487 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::runtime_error,
"Probe requires Isorropia");
2491 double norm_1(
const MultiVector & v,std::size_t col)
2493 Teuchos::Array<double> n(v->domain()->dim());
2494 Thyra::norms_1<double>(*v,n);
2499 double norm_2(
const MultiVector & v,std::size_t col)
2501 Teuchos::Array<double> n(v->domain()->dim());
2502 Thyra::norms_2<double>(*v,n);
2507 void putScalar(
const ModifiableLinearOp & op,
double scalar)
2511 RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
2514 RCP<Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,
true);
2516 eCrsOp->PutScalar(scalar);
2518 catch (std::exception & e) {
2519 RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
2521 *out <<
"Teko: putScalar requires an Epetra_CrsMatrix\n";
2522 *out <<
" Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
2524 *out <<
" Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
2526 *out <<
"*** THROWN EXCEPTION ***\n";
2527 *out << e.what() << std::endl;
2528 *out <<
"************************\n";
2534 void clipLower(MultiVector & v,
double lowerBound)
2537 using Teuchos::rcp_dynamic_cast;
2543 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2544 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2545 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2547 Teuchos::ArrayRCP<double> values;
2549 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2550 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2551 if(values[j]<lowerBound)
2552 values[j] = lowerBound;
2557 void clipUpper(MultiVector & v,
double upperBound)
2560 using Teuchos::rcp_dynamic_cast;
2565 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2566 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2567 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2569 Teuchos::ArrayRCP<double> values;
2571 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2572 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2573 if(values[j]>upperBound)
2574 values[j] = upperBound;
2579 void replaceValue(MultiVector & v,
double currentValue,
double newValue)
2582 using Teuchos::rcp_dynamic_cast;
2587 for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
2588 RCP<Thyra::SpmdVectorBase<double> > spmdVec
2589 = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),
true);
2591 Teuchos::ArrayRCP<double> values;
2593 spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
2594 for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
2595 if(values[j]==currentValue)
2596 values[j] = newValue;
2601 void columnAverages(
const MultiVector & v,std::vector<double> & averages)
2603 averages.resize(v->domain()->dim());
2606 Thyra::sums<double>(*v,averages);
2609 Thyra::Ordinal rows = v->range()->dim();
2610 for(std::size_t i=0;i<averages.size();i++)
2611 averages[i] = averages[i]/rows;
2614 double average(
const MultiVector & v)
2616 Thyra::Ordinal rows = v->range()->dim();
2617 Thyra::Ordinal cols = v->domain()->dim();
2619 std::vector<double> averages;
2620 columnAverages(v,averages);
2623 for(std::size_t i=0;i<averages.size();i++)
2624 sum += averages[i] * rows;
2626 return sum/(rows*cols);
2629 bool isPhysicallyBlockedLinearOp(
const LinearOp & op)
2632 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2633 if (!pblo.is_null())
2638 Thyra::EOpTransp transp = Thyra::NOTRANS;
2639 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2640 Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
2641 pblo = rcp_dynamic_cast<const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op);
2642 if (!pblo.is_null())
2648 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > getPhysicallyBlockedLinearOp(
const LinearOp & op, ST *scalar,
bool *transp)
2651 RCP<const Thyra::PhysicallyBlockedLinearOpBase<double> > pblo = rcp_dynamic_cast<const Thyra::PhysicallyBlockedLinearOpBase<double> >(op);
2652 if(!pblo.is_null()){
2659 RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
2660 Thyra::EOpTransp eTransp = Thyra::NOTRANS;
2661 Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
2662 pblo = rcp_dynamic_cast<const Thyra::PhysicallyBlockedLinearOpBase<double> >(wrapped_op,
true);
2663 if(!pblo.is_null()){
2665 if(eTransp == Thyra::NOTRANS)
2670 return Teuchos::null;
void scale(const double alpha, MultiVector &x)
Scale a multivector by a constant.
DiagonalType
Type describing the type of diagonal to construct.
@ BlkDiag
Specifies that a block diagonal approximation is to be used.
@ NotDiag
For user convenience, if Teko recieves this value, exceptions will be thrown
@ AbsRowSum
Specifies that the diagonal entry is .
@ Diagonal
Specifies that just the diagonal is used.
@ Lumped
Specifies that row sum is used to form a diagonal.
int blockRowCount(const BlockedLinearOp &blo)
Get the row count in a block linear operator.
int blockColCount(const BlockedLinearOp &blo)
Get the column count in a block linear operator.
BlockedLinearOp createBlockedOp()
Build a new blocked linear operator.
Implements the Epetra_Operator interface with a Thyra LinearOperator. This enables the use of absrtac...