Teko  Version of the Day
Teko_Utilities.cpp
1 /*
2 // @HEADER
3 //
4 // ***********************************************************************
5 //
6 // Teko: A package for block and physics based preconditioning
7 // Copyright 2010 Sandia Corporation
8 //
9 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 */
46 
47 #include "Teko_Config.h"
48 #include "Teko_Utilities.hpp"
49 
50 // Thyra includes
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"
70 
71 // Teuchos includes
72 #include "Teuchos_Array.hpp"
73 
74 // Epetra includes
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"
80 
81 #include "EpetraExt_Transpose_RowMatrix.h"
82 #include "EpetraExt_MatrixMatrix.h"
83 
84 // Anasazi includes
85 #include "AnasaziBasicEigenproblem.hpp"
86 #include "AnasaziThyraAdapter.hpp"
87 #include "AnasaziBlockKrylovSchurSolMgr.hpp"
88 #include "AnasaziBlockKrylovSchur.hpp"
89 #include "AnasaziStatusTestMaxIters.hpp"
90 
91 // Isorropia includes
92 #ifdef Teko_ENABLE_Isorropia
93 #include "Isorropia_EpetraProber.hpp"
94 #endif
95 
96 // Teko includes
97 #include "Epetra/Teko_EpetraHelpers.hpp"
98 #include "Epetra/Teko_EpetraOperatorWrapper.hpp"
99 
100 #include <cmath>
101 
102 namespace Teko {
103 
104 using Teuchos::rcp;
105 using Teuchos::rcp_dynamic_cast;
106 using Teuchos::RCP;
107 #ifdef Teko_ENABLE_Isorropia
108 using Isorropia::Epetra::Prober;
109 #endif
110 
111 const Teuchos::RCP<Teuchos::FancyOStream> getOutputStream()
112 {
113  Teuchos::RCP<Teuchos::FancyOStream> os =
114  Teuchos::VerboseObjectBase::getDefaultOStream();
115 
116  //os->setShowProcRank(true);
117  //os->setOutputToRootOnly(-1);
118  return os;
119 }
120 
121 // distance function...not parallel...entirely internal to this cpp file
122 inline double dist(int dim,double * coords,int row,int col)
123 {
124  double value = 0.0;
125  for(int i=0;i<dim;i++)
126  value += std::pow(coords[dim*row+i]-coords[dim*col+i],2.0);
127 
128  // the distance between the two
129  return std::sqrt(value);
130 }
131 
132 // distance function...not parallel...entirely internal to this cpp file
133 inline double dist(double * x,double * y,double * z,int stride,int row,int col)
134 {
135  double value = 0.0;
136  if(x!=0) value += std::pow(x[stride*row]-x[stride*col],2.0);
137  if(y!=0) value += std::pow(y[stride*row]-y[stride*col],2.0);
138  if(z!=0) value += std::pow(z[stride*row]-z[stride*col],2.0);
139 
140  // the distance between the two
141  return std::sqrt(value);
142 }
143 
162 RCP<Epetra_CrsMatrix> buildGraphLaplacian(int dim,double * coords,const Epetra_CrsMatrix & stencil)
163 {
164  // allocate a new matrix with storage for the laplacian...in case of diagonals add one extra storage
165  RCP<Epetra_CrsMatrix> gl = rcp(new Epetra_CrsMatrix(Copy,stencil.RowMap(),stencil.ColMap(),
166  stencil.MaxNumEntries()+1),true);
167 
168  // allocate an additional value for the diagonal, if neccessary
169  std::vector<double> rowData(stencil.GlobalMaxNumEntries()+1);
170  std::vector<int> rowInd(stencil.GlobalMaxNumEntries()+1);
171 
172  // loop over all the rows
173  for(int j=0;j<gl->NumMyRows();j++) {
174  int row = gl->GRID(j);
175  double diagValue = 0.0;
176  int diagInd = -1;
177  int rowSz = 0;
178 
179  // extract a copy of this row...put it in rowData, rowIndicies
180  stencil.ExtractGlobalRowCopy(row,stencil.MaxNumEntries(),rowSz,&rowData[0],&rowInd[0]);
181 
182  // loop over elements of row
183  for(int i=0;i<rowSz;i++) {
184  int col = rowInd[i];
185 
186  // is this a 0 entry masquerading as some thing else?
187  double value = rowData[i];
188  if(value==0) continue;
189 
190  // for nondiagonal entries
191  if(row!=col) {
192  double d = dist(dim,coords,row,col);
193  rowData[i] = -1.0/d;
194  diagValue += rowData[i];
195  }
196  else
197  diagInd = i;
198  }
199 
200  // handle diagonal entry
201  if(diagInd<0) { // diagonal not in row
202  rowData[rowSz] = -diagValue;
203  rowInd[rowSz] = row;
204  rowSz++;
205  }
206  else { // diagonal in row
207  rowData[diagInd] = -diagValue;
208  rowInd[diagInd] = row;
209  }
210 
211  // insert row data into graph Laplacian matrix
212  TEUCHOS_TEST_FOR_EXCEPT(gl->InsertGlobalValues(row,rowSz,&rowData[0],&rowInd[0]));
213  }
214 
215  gl->FillComplete();
216 
217  return gl;
218 }
219 
242 RCP<Epetra_CrsMatrix> buildGraphLaplacian(double * x,double * y,double * z,int stride,const Epetra_CrsMatrix & stencil)
243 {
244  // allocate a new matrix with storage for the laplacian...in case of diagonals add one extra storage
245  RCP<Epetra_CrsMatrix> gl = rcp(new Epetra_CrsMatrix(Copy,stencil.RowMap(),stencil.ColMap(),
246  stencil.MaxNumEntries()+1),true);
247 
248  // allocate an additional value for the diagonal, if neccessary
249  std::vector<double> rowData(stencil.GlobalMaxNumEntries()+1);
250  std::vector<int> rowInd(stencil.GlobalMaxNumEntries()+1);
251 
252  // loop over all the rows
253  for(int j=0;j<gl->NumMyRows();j++) {
254  int row = gl->GRID(j);
255  double diagValue = 0.0;
256  int diagInd = -1;
257  int rowSz = 0;
258 
259  // extract a copy of this row...put it in rowData, rowIndicies
260  stencil.ExtractGlobalRowCopy(row,stencil.MaxNumEntries(),rowSz,&rowData[0],&rowInd[0]);
261 
262  // loop over elements of row
263  for(int i=0;i<rowSz;i++) {
264  int col = rowInd[i];
265 
266  // is this a 0 entry masquerading as some thing else?
267  double value = rowData[i];
268  if(value==0) continue;
269 
270  // for nondiagonal entries
271  if(row!=col) {
272  double d = dist(x,y,z,stride,row,col);
273  rowData[i] = -1.0/d;
274  diagValue += rowData[i];
275  }
276  else
277  diagInd = i;
278  }
279 
280  // handle diagonal entry
281  if(diagInd<0) { // diagonal not in row
282  rowData[rowSz] = -diagValue;
283  rowInd[rowSz] = row;
284  rowSz++;
285  }
286  else { // diagonal in row
287  rowData[diagInd] = -diagValue;
288  rowInd[diagInd] = row;
289  }
290 
291  // insert row data into graph Laplacian matrix
292  TEUCHOS_TEST_FOR_EXCEPT(gl->InsertGlobalValues(row,rowSz,&rowData[0],&rowInd[0]));
293  }
294 
295  gl->FillComplete();
296 
297  return gl;
298 }
299 
315 void applyOp(const LinearOp & A,const MultiVector & x,MultiVector & y,double alpha,double beta)
316 {
317  // Thyra::apply(*A,Thyra::NONCONJ_ELE,*x,&*y,alpha,beta);
318  Thyra::apply(*A,Thyra::NOTRANS,*x,y.ptr(),alpha,beta);
319 }
320 
323 void update(double alpha,const MultiVector & x,double beta,MultiVector & y)
324 {
325  Teuchos::Array<double> scale;
326  Teuchos::Array<Teuchos::Ptr<const Thyra::MultiVectorBase<double> > > vec;
327 
328  // build arrays needed for linear combo
329  scale.push_back(alpha);
330  vec.push_back(x.ptr());
331 
332  // compute linear combination
333  Thyra::linear_combination<double>(scale,vec,beta,y.ptr());
334 }
335 
337 BlockedLinearOp getUpperTriBlocks(const BlockedLinearOp & blo,bool callEndBlockFill)
338 {
339  int rows = blockRowCount(blo);
340 
341  TEUCHOS_ASSERT(rows==blockColCount(blo));
342 
343  RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
344  RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
345 
346  // allocate new operator
347  BlockedLinearOp upper = createBlockedOp();
348 
349  // build new operator
350  upper->beginBlockFill(rows,rows);
351 
352  for(int i=0;i<rows;i++) {
353  // put zero operators on the diagonal
354  // this gurantees the vector space of
355  // the new operator are fully defined
356  RCP<const Thyra::LinearOpBase<double> > zed
357  = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
358  upper->setBlock(i,i,zed);
359 
360  for(int j=i+1;j<rows;j++) {
361  // get block i,j
362  LinearOp uij = blo->getBlock(i,j);
363 
364  // stuff it in U
365  if(uij!=Teuchos::null)
366  upper->setBlock(i,j,uij);
367  }
368  }
369  if(callEndBlockFill)
370  upper->endBlockFill();
371 
372  return upper;
373 }
374 
376 BlockedLinearOp getLowerTriBlocks(const BlockedLinearOp & blo,bool callEndBlockFill)
377 {
378  int rows = blockRowCount(blo);
379 
380  TEUCHOS_ASSERT(rows==blockColCount(blo));
381 
382  RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
383  RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
384 
385  // allocate new operator
386  BlockedLinearOp lower = createBlockedOp();
387 
388  // build new operator
389  lower->beginBlockFill(rows,rows);
390 
391  for(int i=0;i<rows;i++) {
392  // put zero operators on the diagonal
393  // this gurantees the vector space of
394  // the new operator are fully defined
395  RCP<const Thyra::LinearOpBase<double> > zed
396  = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
397  lower->setBlock(i,i,zed);
398 
399  for(int j=0;j<i;j++) {
400  // get block i,j
401  LinearOp uij = blo->getBlock(i,j);
402 
403  // stuff it in U
404  if(uij!=Teuchos::null)
405  lower->setBlock(i,j,uij);
406  }
407  }
408  if(callEndBlockFill)
409  lower->endBlockFill();
410 
411  return lower;
412 }
413 
433 BlockedLinearOp zeroBlockedOp(const BlockedLinearOp & blo)
434 {
435  int rows = blockRowCount(blo);
436 
437  TEUCHOS_ASSERT(rows==blockColCount(blo)); // assert that matrix is square
438 
439  RCP<const Thyra::ProductVectorSpaceBase<double> > range = blo->productRange();
440  RCP<const Thyra::ProductVectorSpaceBase<double> > domain = blo->productDomain();
441 
442  // allocate new operator
443  BlockedLinearOp zeroOp = createBlockedOp();
444 
445  // build new operator
446  zeroOp->beginBlockFill(rows,rows);
447 
448  for(int i=0;i<rows;i++) {
449  // put zero operators on the diagonal
450  // this gurantees the vector space of
451  // the new operator are fully defined
452  RCP<const Thyra::LinearOpBase<double> > zed
453  = Thyra::zero<double>(range->getBlock(i),domain->getBlock(i));
454  zeroOp->setBlock(i,i,zed);
455  }
456 
457  return zeroOp;
458 }
459 
461 bool isZeroOp(const LinearOp op)
462 {
463  // if operator is null...then its zero!
464  if(op==Teuchos::null) return true;
465 
466  // try to cast it to a zero linear operator
467  const LinearOp test = rcp_dynamic_cast<const Thyra::ZeroLinearOpBase<double> >(op);
468 
469  // if it works...then its zero...otherwise its null
470  return test!=Teuchos::null;
471 }
472 
481 ModifiableLinearOp getAbsRowSumMatrix(const LinearOp & op)
482 {
483  RCP<const Epetra_CrsMatrix> eCrsOp;
484 
485  try {
486  // get Epetra_Operator
487  RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
488 
489  // cast it to a CrsMatrix
490  eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp,true);
491  }
492  catch (std::exception & e) {
493  RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
494 
495  *out << "Teko: getAbsRowSumMatrix requires an Epetra_CrsMatrix\n";
496  *out << " Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
497  *out << " OR\n";
498  *out << " Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
499  *out << std::endl;
500  *out << "*** THROWN EXCEPTION ***\n";
501  *out << e.what() << std::endl;
502  *out << "************************\n";
503 
504  throw e;
505  }
506 
507  // extract diagonal
508  const RCP<Epetra_Vector> ptrDiag = rcp(new Epetra_Vector(eCrsOp->RowMap()));
509  Epetra_Vector & diag = *ptrDiag;
510 
511  // compute absolute value row sum
512  diag.PutScalar(0.0);
513  for(int i=0;i<eCrsOp->NumMyRows();i++) {
514  double * values = 0;
515  int numEntries;
516  eCrsOp->ExtractMyRowView(i,numEntries,values);
517 
518  // build abs value row sum
519  for(int j=0;j<numEntries;j++)
520  diag[i] += std::abs(values[j]);
521  }
522 
523  // build Thyra diagonal operator
524  return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),"absRowSum( " + op->getObjectLabel() + " )");
525 }
526 
535 ModifiableLinearOp getAbsRowSumInvMatrix(const LinearOp & op)
536 {
537  RCP<const Epetra_CrsMatrix> eCrsOp;
538 
539  try {
540  // get Epetra_Operator
541  RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
542 
543  // cast it to a CrsMatrix
544  eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp,true);
545  }
546  catch (std::exception & e) {
547  RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
548 
549  *out << "Teko: getAbsRowSumMatrix requires an Epetra_CrsMatrix\n";
550  *out << " Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
551  *out << " OR\n";
552  *out << " Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
553  *out << std::endl;
554  *out << "*** THROWN EXCEPTION ***\n";
555  *out << e.what() << std::endl;
556  *out << "************************\n";
557 
558  throw e;
559  }
560 
561  // extract diagonal
562  const RCP<Epetra_Vector> ptrDiag = rcp(new Epetra_Vector(eCrsOp->RowMap()));
563  Epetra_Vector & diag = *ptrDiag;
564 
565  // compute absolute value row sum
566  diag.PutScalar(0.0);
567  for(int i=0;i<eCrsOp->NumMyRows();i++) {
568  double * values = 0;
569  int numEntries;
570  eCrsOp->ExtractMyRowView(i,numEntries,values);
571 
572  // build abs value row sum
573  for(int j=0;j<numEntries;j++)
574  diag[i] += std::abs(values[j]);
575  }
576  diag.Reciprocal(diag); // invert entries
577 
578  // build Thyra diagonal operator
579  return Teko::Epetra::thyraDiagOp(ptrDiag,eCrsOp->RowMap(),"absRowSumInv( " + op->getObjectLabel() + " )");
580 }
581 
589 ModifiableLinearOp getLumpedMatrix(const LinearOp & op)
590 {
591  RCP<Thyra::VectorBase<double> > ones = Thyra::createMember(op->domain());
592  RCP<Thyra::VectorBase<double> > diag = Thyra::createMember(op->range());
593 
594  // set to all ones
595  Thyra::assign(ones.ptr(),1.0);
596 
597  // compute lumped diagonal
598  // Thyra::apply(*op,Thyra::NONCONJ_ELE,*ones,&*diag);
599  Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
600 
601  return rcp(new Thyra::DefaultDiagonalLinearOp<double>(diag));
602 }
603 
612 ModifiableLinearOp getInvLumpedMatrix(const LinearOp & op)
613 {
614  RCP<Thyra::VectorBase<double> > ones = Thyra::createMember(op->domain());
615  RCP<Thyra::VectorBase<double> > diag = Thyra::createMember(op->range());
616 
617  // set to all ones
618  Thyra::assign(ones.ptr(),1.0);
619 
620  // compute lumped diagonal
621  Thyra::apply(*op,Thyra::NOTRANS,*ones,diag.ptr());
622  Thyra::reciprocal(*diag,diag.ptr());
623 
624  return rcp(new Thyra::DefaultDiagonalLinearOp<double>(diag));
625 }
626 
638 const ModifiableLinearOp getDiagonalOp(const LinearOp & op)
639 {
640  RCP<const Epetra_CrsMatrix> eCrsOp;
641 
642  try {
643  // get Epetra_Operator
644  RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
645 
646  // cast it to a CrsMatrix
647  eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp,true);
648  }
649  catch (std::exception & e) {
650  RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
651 
652  *out << "Teko: getDiagonalOp requires an Epetra_CrsMatrix\n";
653  *out << " Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
654  *out << " OR\n";
655  *out << " Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
656  *out << std::endl;
657  *out << "*** THROWN EXCEPTION ***\n";
658  *out << e.what() << std::endl;
659  *out << "************************\n";
660 
661  throw e;
662  }
663 
664  // extract diagonal
665  const RCP<Epetra_Vector> diag = rcp(new Epetra_Vector(eCrsOp->RowMap()));
666  TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
667 
668  // build Thyra diagonal operator
669  return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),"diag( " + op->getObjectLabel() + " )");
670 }
671 
672 const MultiVector getDiagonal(const LinearOp & op)
673 {
674  RCP<const Epetra_CrsMatrix> eCrsOp;
675 
676  try {
677  // get Epetra_Operator
678  RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
679 
680  // cast it to a CrsMatrix
681  eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp,true);
682  }
683  catch (std::exception & e) {
684  RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
685 
686  *out << "Teko: getDiagonal requires an Epetra_CrsMatrix\n";
687  *out << " Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
688  *out << " OR\n";
689  *out << " Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
690  *out << std::endl;
691  *out << "*** THROWN EXCEPTION ***\n";
692  *out << e.what() << std::endl;
693  *out << "************************\n";
694 
695  throw e;
696  }
697 
698  // extract diagonal
699  const RCP<Epetra_Vector> diag = rcp(new Epetra_Vector(eCrsOp->RowMap()));
700  TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
701 
702  return Thyra::create_Vector(diag,Thyra::create_VectorSpace(Teuchos::rcpFromRef(eCrsOp->RowMap())));
703 }
704 
705 const MultiVector getDiagonal(const Teko::LinearOp & A,const DiagonalType & dt)
706 {
707  LinearOp diagOp = Teko::getDiagonalOp(A,dt);
708 
709  Teuchos::RCP<const Thyra::MultiVectorBase<double> > v =
710  Teuchos::rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<double> >(diagOp)->getDiag();
711  return Teuchos::rcp_const_cast<Thyra::MultiVectorBase<double> >(v);
712 }
713 
725 const ModifiableLinearOp getInvDiagonalOp(const LinearOp & op)
726 {
727  RCP<const Epetra_CrsMatrix> eCrsOp;
728 
729  try {
730  // get Epetra_Operator
731  RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
732 
733  // cast it to a CrsMatrix
734  eCrsOp = rcp_dynamic_cast<const Epetra_CrsMatrix>(eOp,true);
735  }
736  catch (std::exception & e) {
737  RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
738 
739  *out << "Teko: getInvDiagonalOp requires an Epetra_CrsMatrix\n";
740  *out << " Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
741  *out << " OR\n";
742  *out << " Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
743  *out << std::endl;
744  *out << "*** THROWN EXCEPTION ***\n";
745  *out << e.what() << std::endl;
746  *out << "************************\n";
747 
748  throw e;
749  }
750 
751  // extract diagonal
752  const RCP<Epetra_Vector> diag = rcp(new Epetra_Vector(eCrsOp->RowMap()));
753  TEUCHOS_TEST_FOR_EXCEPT(eCrsOp->ExtractDiagonalCopy(*diag));
754  diag->Reciprocal(*diag);
755 
756  // build Thyra diagonal operator
757  return Teko::Epetra::thyraDiagOp(diag,eCrsOp->RowMap(),"inv(diag( " + op->getObjectLabel() + " ))");
758 }
759 
772 const LinearOp explicitMultiply(const LinearOp & opl,const LinearOp & opm,const LinearOp & opr)
773 {
774  // build implicit multiply
775  const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
776 
777  // build transformer
778  const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
779  Thyra::epetraExtDiagScaledMatProdTransformer();
780 
781  // build operator and multiply
782  const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
783  prodTrans->transform(*implicitOp,explicitOp.ptr());
784  explicitOp->setObjectLabel("explicit( " + opl->getObjectLabel() +
785  " * " + opm->getObjectLabel() +
786  " * " + opr->getObjectLabel() + " )");
787 
788  return explicitOp;
789 }
790 
805 const ModifiableLinearOp explicitMultiply(const LinearOp & opl,const LinearOp & opm,const LinearOp & opr,
806  const ModifiableLinearOp & destOp)
807 {
808  // build implicit multiply
809  const LinearOp implicitOp = Thyra::multiply(opl,opm,opr);
810 
811  // build transformer
812  const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
813  Thyra::epetraExtDiagScaledMatProdTransformer();
814 
815  // build operator destination operator
816  ModifiableLinearOp explicitOp;
817 
818  // if neccessary build a operator to put the explicit multiply into
819  if(destOp==Teuchos::null)
820  explicitOp = prodTrans->createOutputOp();
821  else
822  explicitOp = destOp;
823 
824  // perform multiplication
825  prodTrans->transform(*implicitOp,explicitOp.ptr());
826 
827  // label it
828  explicitOp->setObjectLabel("explicit( " + opl->getObjectLabel() +
829  " * " + opm->getObjectLabel() +
830  " * " + opr->getObjectLabel() + " )");
831 
832  return explicitOp;
833 }
834 
845 const LinearOp explicitMultiply(const LinearOp & opl,const LinearOp & opr)
846 {
847  // build implicit multiply
848  const LinearOp implicitOp = Thyra::multiply(opl,opr);
849 
850  // build a scaling transformer
851  RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
852  = Thyra::epetraExtDiagScalingTransformer();
853 
854  // check to see if a scaling transformer works: if not use the
855  // DiagScaledMatrixProduct transformer
856  if(not prodTrans->isCompatible(*implicitOp))
857  prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
858 
859  // build operator and multiply
860  const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
861  prodTrans->transform(*implicitOp,explicitOp.ptr());
862  explicitOp->setObjectLabel("explicit( " + opl->getObjectLabel() +
863  " * " + opr->getObjectLabel() + " )");
864 
865  return explicitOp;
866 }
867 
881 const ModifiableLinearOp explicitMultiply(const LinearOp & opl,const LinearOp & opr,
882  const ModifiableLinearOp & destOp)
883 {
884  // build implicit multiply
885  const LinearOp implicitOp = Thyra::multiply(opl,opr);
886 
887  // build a scaling transformer
888  RCP<Thyra::LinearOpTransformerBase<double> > prodTrans
889  = Thyra::epetraExtDiagScalingTransformer();
890 
891  // check to see if a scaling transformer works: if not use the
892  // DiagScaledMatrixProduct transformer
893  if(not prodTrans->isCompatible(*implicitOp))
894  prodTrans = Thyra::epetraExtDiagScaledMatProdTransformer();
895 
896  // build operator destination operator
897  ModifiableLinearOp explicitOp;
898 
899  // if neccessary build a operator to put the explicit multiply into
900  if(destOp==Teuchos::null)
901  explicitOp = prodTrans->createOutputOp();
902  else
903  explicitOp = destOp;
904 
905  // perform multiplication
906  prodTrans->transform(*implicitOp,explicitOp.ptr());
907 
908  // label it
909  explicitOp->setObjectLabel("explicit( " + opl->getObjectLabel() +
910  " * " + opr->getObjectLabel() + " )");
911 
912  return explicitOp;
913 }
914 
925 const LinearOp explicitAdd(const LinearOp & opl,const LinearOp & opr)
926 {
927  // build implicit multiply
928  const LinearOp implicitOp = Thyra::add(opl,opr);
929 
930  // build transformer
931  const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
932  Thyra::epetraExtAddTransformer();
933 
934  // build operator and multiply
935  const RCP<Thyra::LinearOpBase<double> > explicitOp = prodTrans->createOutputOp();
936  prodTrans->transform(*implicitOp,explicitOp.ptr());
937  explicitOp->setObjectLabel("explicit( " + opl->getObjectLabel() +
938  " + " + opr->getObjectLabel() + " )");
939 
940  return explicitOp;
941 }
942 
955 const ModifiableLinearOp explicitAdd(const LinearOp & opl,const LinearOp & opr,
956  const ModifiableLinearOp & destOp)
957 {
958  // build implicit multiply
959  const LinearOp implicitOp = Thyra::add(opl,opr);
960 
961  // build transformer
962  const RCP<Thyra::LinearOpTransformerBase<double> > prodTrans =
963  Thyra::epetraExtAddTransformer();
964 
965  // build or reuse destination operator
966  RCP<Thyra::LinearOpBase<double> > explicitOp;
967  if(destOp!=Teuchos::null)
968  explicitOp = destOp;
969  else
970  explicitOp = prodTrans->createOutputOp();
971 
972  // perform multiplication
973  prodTrans->transform(*implicitOp,explicitOp.ptr());
974  explicitOp->setObjectLabel("explicit( " + opl->getObjectLabel() +
975  " + " + opr->getObjectLabel() + " )");
976 
977  return explicitOp;
978 }
979 
984 const ModifiableLinearOp explicitSum(const LinearOp & op,
985  const ModifiableLinearOp & destOp)
986 {
987  // convert operators to Epetra_CrsMatrix
988  const RCP<const Epetra_CrsMatrix> epetraOp =
989  rcp_dynamic_cast<const Epetra_CrsMatrix>(get_Epetra_Operator(*op), true);
990 
991  if(destOp==Teuchos::null) {
992  Teuchos::RCP<Epetra_Operator> epetraDest = Teuchos::rcp(new Epetra_CrsMatrix(*epetraOp));
993 
994  return Thyra::nonconstEpetraLinearOp(epetraDest);
995  }
996 
997  const RCP<Epetra_CrsMatrix> epetraDest =
998  rcp_dynamic_cast<Epetra_CrsMatrix>(get_Epetra_Operator(*destOp), true);
999 
1000  EpetraExt::MatrixMatrix::Add(*epetraOp,false,1.0,*epetraDest,1.0);
1001 
1002  return destOp;
1003 }
1004 
1005 const LinearOp explicitTranspose(const LinearOp & op)
1006 {
1007  RCP<const Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
1008  TEUCHOS_TEST_FOR_EXCEPTION(eOp==Teuchos::null,std::logic_error,
1009  "Teko::explicitTranspose Not an Epetra_Operator");
1010  RCP<const Epetra_RowMatrix> eRowMatrixOp
1011  = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(eOp);
1012  TEUCHOS_TEST_FOR_EXCEPTION(eRowMatrixOp==Teuchos::null,std::logic_error,
1013  "Teko::explicitTranspose Not an Epetra_RowMatrix");
1014 
1015  // we now have a delete transpose operator
1016  EpetraExt::RowMatrix_Transpose tranposeOp;
1017  Epetra_RowMatrix & eMat = tranposeOp(const_cast<Epetra_RowMatrix &>(*eRowMatrixOp));
1018 
1019  // this copy is because of a poor implementation of the EpetraExt::Transform
1020  // implementation
1021  Teuchos::RCP<Epetra_CrsMatrix> crsMat
1022  = Teuchos::rcp(new Epetra_CrsMatrix(dynamic_cast<Epetra_CrsMatrix &>(eMat)));
1023 
1024  return Thyra::epetraLinearOp(crsMat);
1025 }
1026 
1027 const LinearOp buildDiagonal(const MultiVector & src,const std::string & lbl)
1028 {
1029  RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(src->range());
1030  Thyra::copy(*src->col(0),dst.ptr());
1031 
1032  return Thyra::diagonal<double>(dst,lbl);
1033 }
1034 
1035 const LinearOp buildInvDiagonal(const MultiVector & src,const std::string & lbl)
1036 {
1037  const RCP<const Thyra::VectorBase<double> > srcV = src->col(0);
1038  RCP<Thyra::VectorBase<double> > dst = Thyra::createMember(srcV->range());
1039  Thyra::reciprocal<double>(*srcV,dst.ptr());
1040 
1041  return Thyra::diagonal<double>(dst,lbl);
1042 }
1043 
1045 BlockedMultiVector buildBlockedMultiVector(const std::vector<MultiVector> & mvv)
1046 {
1047  Teuchos::Array<MultiVector> mvA;
1048  Teuchos::Array<VectorSpace> vsA;
1049 
1050  // build arrays of multi vectors and vector spaces
1051  std::vector<MultiVector>::const_iterator itr;
1052  for(itr=mvv.begin();itr!=mvv.end();++itr) {
1053  mvA.push_back(*itr);
1054  vsA.push_back((*itr)->range());
1055  }
1056 
1057  // construct the product vector space
1058  const RCP<const Thyra::DefaultProductVectorSpace<double> > vs
1059  = Thyra::productVectorSpace<double>(vsA);
1060 
1061  return Thyra::defaultProductMultiVector<double>(vs,mvA);
1062 }
1063 
1074 Teuchos::RCP<Thyra::VectorBase<double> > indicatorVector(
1075  const std::vector<int> & indices,
1076  const VectorSpace & vs,
1077  double onValue, double offValue)
1078 
1079 {
1080  using Teuchos::RCP;
1081 
1082  // create a new vector
1083  RCP<Thyra::VectorBase<double> > v = Thyra::createMember<double>(vs);
1084  Thyra::put_scalar<double>(offValue,v.ptr()); // fill it with "off" values
1085 
1086  // set on values
1087  for(std::size_t i=0;i<indices.size();i++)
1088  Thyra::set_ele<double>(indices[i],onValue,v.ptr());
1089 
1090  return v;
1091 }
1092 
1117 double computeSpectralRad(const RCP<const Thyra::LinearOpBase<double> > & A, double tol,
1118  bool isHermitian,int numBlocks,int restart,int verbosity)
1119 {
1120  typedef Thyra::LinearOpBase<double> OP;
1121  typedef Thyra::MultiVectorBase<double> MV;
1122 
1123  int startVectors = 1;
1124 
1125  // construct an initial guess
1126  const RCP<MV> ivec = Thyra::createMember(A->domain());
1127  Thyra::randomize(-1.0,1.0,ivec.ptr());
1128 
1129  RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
1130  = rcp(new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
1131  eigProb->setNEV(1);
1132  eigProb->setHermitian(isHermitian);
1133 
1134  // set the problem up
1135  if(not eigProb->setProblem()) {
1136  // big time failure!
1137  return Teuchos::ScalarTraits<double>::nan();
1138  }
1139 
1140  // we want largert magnitude eigenvalue
1141  std::string which("LM"); // largest magnitude
1142 
1143  // Create the parameter list for the eigensolver
1144  // verbosity+=Anasazi::TimingDetails;
1145  Teuchos::ParameterList MyPL;
1146  MyPL.set( "Verbosity", verbosity );
1147  MyPL.set( "Which", which );
1148  MyPL.set( "Block Size", startVectors );
1149  MyPL.set( "Num Blocks", numBlocks );
1150  MyPL.set( "Maximum Restarts", restart );
1151  MyPL.set( "Convergence Tolerance", tol );
1152 
1153  // build status test manager
1154  // RCP<Anasazi::StatusTestMaxIters<double,MV,OP> > statTest
1155  // = rcp(new Anasazi::StatusTestMaxIters<double,MV,OP>(numBlocks*(restart+1)));
1156 
1157  // Create the Block Krylov Schur solver
1158  // This takes as inputs the eigenvalue problem and the solver parameters
1159  Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
1160 
1161  // Solve the eigenvalue problem, and save the return code
1162  Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
1163 
1164  if(solverreturn==Anasazi::Unconverged) {
1165  double real = MyBlockKrylovSchur.getRitzValues().begin()->realpart;
1166  double comp = MyBlockKrylovSchur.getRitzValues().begin()->imagpart;
1167 
1168  return -std::abs(std::sqrt(real*real+comp*comp));
1169 
1170  // cout << "Anasazi::BlockKrylovSchur::solve() did not converge!" << std::endl;
1171  // return -std::abs(MyBlockKrylovSchur.getRitzValues().begin()->realpart);
1172  }
1173  else { // solverreturn==Anasazi::Converged
1174  double real = eigProb->getSolution().Evals.begin()->realpart;
1175  double comp = eigProb->getSolution().Evals.begin()->imagpart;
1176 
1177  return std::abs(std::sqrt(real*real+comp*comp));
1178 
1179  // cout << "Anasazi::BlockKrylovSchur::solve() converged!" << endl;
1180  // return std::abs(eigProb->getSolution().Evals.begin()->realpart);
1181  }
1182 }
1183 
1207 double computeSmallestMagEig(const RCP<const Thyra::LinearOpBase<double> > & A, double tol,
1208  bool isHermitian,int numBlocks,int restart,int verbosity)
1209 {
1210  typedef Thyra::LinearOpBase<double> OP;
1211  typedef Thyra::MultiVectorBase<double> MV;
1212 
1213  int startVectors = 1;
1214 
1215  // construct an initial guess
1216  const RCP<MV> ivec = Thyra::createMember(A->domain());
1217  Thyra::randomize(-1.0,1.0,ivec.ptr());
1218 
1219  RCP<Anasazi::BasicEigenproblem<double,MV,OP> > eigProb
1220  = rcp(new Anasazi::BasicEigenproblem<double,MV,OP>(A,ivec));
1221  eigProb->setNEV(1);
1222  eigProb->setHermitian(isHermitian);
1223 
1224  // set the problem up
1225  if(not eigProb->setProblem()) {
1226  // big time failure!
1227  return Teuchos::ScalarTraits<double>::nan();
1228  }
1229 
1230  // we want largert magnitude eigenvalue
1231  std::string which("SM"); // smallest magnitude
1232 
1233  // Create the parameter list for the eigensolver
1234  Teuchos::ParameterList MyPL;
1235  MyPL.set( "Verbosity", verbosity );
1236  MyPL.set( "Which", which );
1237  MyPL.set( "Block Size", startVectors );
1238  MyPL.set( "Num Blocks", numBlocks );
1239  MyPL.set( "Maximum Restarts", restart );
1240  MyPL.set( "Convergence Tolerance", tol );
1241 
1242  // build status test manager
1243  // RCP<Anasazi::StatusTestMaxIters<double,MV,OP> > statTest
1244  // = rcp(new Anasazi::StatusTestMaxIters<double,MV,OP>(10));
1245 
1246  // Create the Block Krylov Schur solver
1247  // This takes as inputs the eigenvalue problem and the solver parameters
1248  Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MyBlockKrylovSchur(eigProb, MyPL );
1249 
1250  // Solve the eigenvalue problem, and save the return code
1251  Anasazi::ReturnType solverreturn = MyBlockKrylovSchur.solve();
1252 
1253  if(solverreturn==Anasazi::Unconverged) {
1254  // cout << "Anasazi::BlockKrylovSchur::solve() did not converge! " << std::endl;
1255  return -std::abs(MyBlockKrylovSchur.getRitzValues().begin()->realpart);
1256  }
1257  else { // solverreturn==Anasazi::Converged
1258  // cout << "Anasazi::BlockKrylovSchur::solve() converged!" << endl;
1259  return std::abs(eigProb->getSolution().Evals.begin()->realpart);
1260  }
1261 }
1262 
1271 ModifiableLinearOp getDiagonalOp(const Teko::LinearOp & A,const DiagonalType & dt)
1272 {
1273  switch(dt) {
1274  case Diagonal:
1275  return getDiagonalOp(A);
1276  case Lumped:
1277  return getLumpedMatrix(A);
1278  case AbsRowSum:
1279  return getAbsRowSumMatrix(A);
1280  case NotDiag:
1281  default:
1282  TEUCHOS_TEST_FOR_EXCEPT(true);
1283  };
1284 
1285  return Teuchos::null;
1286 }
1287 
1296 ModifiableLinearOp getInvDiagonalOp(const Teko::LinearOp & A,const Teko::DiagonalType & dt)
1297 {
1298  switch(dt) {
1299  case Diagonal:
1300  return getInvDiagonalOp(A);
1301  case Lumped:
1302  return getInvLumpedMatrix(A);
1303  case AbsRowSum:
1304  return getAbsRowSumInvMatrix(A);
1305  case NotDiag:
1306  default:
1307  TEUCHOS_TEST_FOR_EXCEPT(true);
1308  };
1309 
1310  return Teuchos::null;
1311 }
1312 
1319 std::string getDiagonalName(const DiagonalType & dt)
1320 {
1321  switch(dt) {
1322  case Diagonal:
1323  return "Diagonal";
1324  case Lumped:
1325  return "Lumped";
1326  case AbsRowSum:
1327  return "AbsRowSum";
1328  case NotDiag:
1329  return "NotDiag";
1330  case BlkDiag:
1331  return "BlkDiag";
1332  };
1333 
1334  return "<error>";
1335 }
1336 
1345 DiagonalType getDiagonalType(std::string name)
1346 {
1347  if(name=="Diagonal")
1348  return Diagonal;
1349  if(name=="Lumped")
1350  return Lumped;
1351  if(name=="AbsRowSum")
1352  return AbsRowSum;
1353  if(name=="BlkDiag")
1354  return BlkDiag;
1355 
1356  return NotDiag;
1357 }
1358 
1359 LinearOp probe(Teuchos::RCP<const Epetra_CrsGraph> &G,const LinearOp & Op){
1360 #ifdef Teko_ENABLE_Isorropia
1361  Teuchos::ParameterList probeList;
1362  Prober prober(G,probeList,true);
1363  Teuchos::RCP<Epetra_CrsMatrix> Mat=rcp(new Epetra_CrsMatrix(Copy,*G));
1365  prober.probe(Mwrap,*Mat);
1366  return Thyra::epetraLinearOp(Mat);
1367 #else
1368  TEUCHOS_TEST_FOR_EXCEPTION(true,std::runtime_error,"Probe requires Isorropia");
1369 #endif
1370 }
1371 
1372 double norm_1(const MultiVector & v,std::size_t col)
1373 {
1374  Teuchos::Array<double> n(v->domain()->dim());
1375  Thyra::norms_1<double>(*v,n);
1376 
1377  return n[col];
1378 }
1379 
1380 double norm_2(const MultiVector & v,std::size_t col)
1381 {
1382  Teuchos::Array<double> n(v->domain()->dim());
1383  Thyra::norms_2<double>(*v,n);
1384 
1385  return n[col];
1386 }
1387 
1388 void putScalar(const ModifiableLinearOp & op,double scalar)
1389 {
1390  try {
1391  // get Epetra_Operator
1392  RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*op);
1393 
1394  // cast it to a CrsMatrix
1395  RCP<Epetra_CrsMatrix> eCrsOp = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,true);
1396 
1397  eCrsOp->PutScalar(scalar);
1398  }
1399  catch (std::exception & e) {
1400  RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream();
1401 
1402  *out << "Teko: putScalar requires an Epetra_CrsMatrix\n";
1403  *out << " Could not extract an Epetra_Operator from a \"" << op->description() << std::endl;
1404  *out << " OR\n";
1405  *out << " Could not cast an Epetra_Operator to a Epetra_CrsMatrix\n";
1406  *out << std::endl;
1407  *out << "*** THROWN EXCEPTION ***\n";
1408  *out << e.what() << std::endl;
1409  *out << "************************\n";
1410 
1411  throw e;
1412  }
1413 }
1414 
1415 void clipLower(MultiVector & v,double lowerBound)
1416 {
1417  using Teuchos::RCP;
1418  using Teuchos::rcp_dynamic_cast;
1419 
1420  // cast so entries are accessible
1421  // RCP<Thyra::SpmdMultiVectorBase<double> > spmdMVec
1422  // = rcp_dynamic_cast<Thyra::DefaultSpmdMultiVector<double> >(v);
1423 
1424  for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
1425  RCP<Thyra::SpmdVectorBase<double> > spmdVec
1426  = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),true);
1427 
1428  Teuchos::ArrayRCP<double> values;
1429  // spmdMVec->getNonconstLocalData(Teuchos::ptrFromRef(values),Teuchos::ptrFromRef(i));
1430  spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
1431  for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
1432  if(values[j]<lowerBound)
1433  values[j] = lowerBound;
1434  }
1435  }
1436 }
1437 
1438 void clipUpper(MultiVector & v,double upperBound)
1439 {
1440  using Teuchos::RCP;
1441  using Teuchos::rcp_dynamic_cast;
1442 
1443  // cast so entries are accessible
1444  // RCP<Thyra::SpmdMultiVectorBase<double> > spmdMVec
1445  // = rcp_dynamic_cast<Thyra::DefaultSpmdMultiVector<double> >(v);
1446  for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
1447  RCP<Thyra::SpmdVectorBase<double> > spmdVec
1448  = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),true);
1449 
1450  Teuchos::ArrayRCP<double> values;
1451  // spmdMVec->getNonconstLocalData(Teuchos::ptrFromRef(values),Teuchos::ptrFromRef(i));
1452  spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
1453  for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
1454  if(values[j]>upperBound)
1455  values[j] = upperBound;
1456  }
1457  }
1458 }
1459 
1460 void replaceValue(MultiVector & v,double currentValue,double newValue)
1461 {
1462  using Teuchos::RCP;
1463  using Teuchos::rcp_dynamic_cast;
1464 
1465  // cast so entries are accessible
1466  // RCP<Thyra::SpmdMultiVectorBase<double> > spmdMVec
1467  // = rcp_dynamic_cast<Thyra::SpmdMultiVectorBase<double> >(v,true);
1468  for(Thyra::Ordinal i=0;i<v->domain()->dim();i++) {
1469  RCP<Thyra::SpmdVectorBase<double> > spmdVec
1470  = rcp_dynamic_cast<Thyra::SpmdVectorBase<double> >(v->col(i),true);
1471 
1472  Teuchos::ArrayRCP<double> values;
1473  // spmdMVec->getNonconstLocalData(Teuchos::ptrFromRef(values),Teuchos::ptrFromRef(i));
1474  spmdVec->getNonconstLocalData(Teuchos::ptrFromRef(values));
1475  for(Teuchos::ArrayRCP<double>::size_type j=0;j<values.size();j++) {
1476  if(values[j]==currentValue)
1477  values[j] = newValue;
1478  }
1479  }
1480 }
1481 
1482 void columnAverages(const MultiVector & v,std::vector<double> & averages)
1483 {
1484  averages.resize(v->domain()->dim());
1485 
1486  // sum over each column
1487  Thyra::sums<double>(*v,averages);
1488 
1489  // build averages
1490  Thyra::Ordinal rows = v->range()->dim();
1491  for(std::size_t i=0;i<averages.size();i++)
1492  averages[i] = averages[i]/rows;
1493 }
1494 
1495 double average(const MultiVector & v)
1496 {
1497  Thyra::Ordinal rows = v->range()->dim();
1498  Thyra::Ordinal cols = v->domain()->dim();
1499 
1500  std::vector<double> averages;
1501  columnAverages(v,averages);
1502 
1503  double sum = 0.0;
1504  for(std::size_t i=0;i<averages.size();i++)
1505  sum += averages[i] * rows;
1506 
1507  return sum/(rows*cols);
1508 }
1509 
1510 }
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 .