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