45 #include "Epetra_Operator.h"
46 #include "Epetra_RowMatrix.h"
47 #include "Epetra_Comm.h"
48 #include "Epetra_Map.h"
49 #include "Epetra_MultiVector.h"
50 #include "Epetra_Vector.h"
51 #include "Epetra_Time.h"
55 #ifdef HAVE_IFPACK_AZTECOO
60 #ifdef HAVE_IFPACK_EPETRAEXT
61 #include "Epetra_CrsMatrix.h"
62 #include "EpetraExt_PointToBlockDiagPermute.h"
66 #define ABS(x) ((x)>0?(x):-(x))
84 IsInitialized_(
false),
91 ApplyInverseTime_(0.0),
93 ApplyInverseFlops_(0.0),
102 MinDiagonalValue_(0.0),
106 NumGlobalNonzeros_(0),
108 UseBlockMode_(
false),
109 SolveNormalEquations_(
false),
111 ZeroStartingSolution_(
true)
126 IsInitialized_(
false),
131 InitializeTime_(0.0),
133 ApplyInverseTime_(0.0),
135 ApplyInverseFlops_(0.0),
137 UseTranspose_(
false),
145 MinDiagonalValue_(0.0),
149 NumGlobalNonzeros_(0),
152 UseBlockMode_(
false),
153 SolveNormalEquations_(
false),
155 ZeroStartingSolution_(
true)
176 #ifdef HAVE_IFPACK_EPETRAEXT
181 BlockList_ = List.
get(
"chebyshev: block list",BlockList_);
186 Blist=BlockList_.
get(
"blockdiagmatrix: list",Blist);
187 std::string dummy(
"invert");
188 std::string ApplyMode=Blist.
get(
"apply mode",dummy);
189 if(ApplyMode==std::string(
"multiply")){
190 Blist.
set(
"apply mode",
"invert");
191 BlockList_.
set(
"blockdiagmatrix: list",Blist);
256 if (
Time_ == Teuchos::null)
261 if (
Matrix().NumGlobalRows64() !=
Matrix().NumGlobalCols64())
271 if (
Operator_->OperatorDomainMap().NumGlobalElements64() !=
272 Operator_->OperatorRangeMap().NumGlobalElements64())
288 Time_->ResetStartTime();
297 #ifdef HAVE_IFPACK_EPETRAEXT
308 InvBlockDiagonal_ =
Teuchos::rcp(
new EpetraExt_PointToBlockDiagPermute(*CrsMatrix));
309 if (InvBlockDiagonal_ == Teuchos::null)
312 ierr = InvBlockDiagonal_->SetParameters(BlockList_);
316 ierr = InvBlockDiagonal_->Compute();
322 double lambda_max = 0;
347 double diag = (*InvDiagonal_)[i];
364 #ifdef IFPACK_FLOPCOUNTERS
382 double MyMinVal, MyMaxVal;
383 double MinVal, MaxVal;
392 if (!
Comm().MyPID()) {
394 os <<
"================================================================================" << endl;
395 os <<
"Ifpack_Chebyshev" << endl;
396 os <<
"Degree of polynomial = " <<
PolyDegree_ << endl;
397 os <<
"Condition number estimate = " <<
Condest() << endl;
398 os <<
"Global number of rows = " <<
Operator_->OperatorRangeMap().NumGlobalElements64() << endl;
400 os <<
"Minimum value on stored inverse diagonal = " << MinVal << endl;
401 os <<
"Maximum value on stored inverse diagonal = " << MaxVal << endl;
404 os <<
"Using zero starting solution" << endl;
406 os <<
"Using input starting solution" << endl;
408 os <<
"Phase # calls Total Time (s) Total MFlops MFlops/s" << endl;
409 os <<
"----- ------- -------------- ------------ --------" << endl;
412 <<
" 0.0 0.0" << endl;
419 os <<
" " << std::setw(15) << 0.0 << endl;
426 os <<
" " << std::setw(15) << 0.0 << endl;
427 os <<
"================================================================================" << endl;
437 const int MaxIters,
const double Tol,
453 std::ostringstream oss;
454 oss <<
"\"Ifpack Chebyshev polynomial\": {"
456 <<
", Computed: " << (
IsComputed() ?
"true" :
"false")
480 Time_->ResetStartTime();
484 Teuchos::RefCountPtr<const Epetra_MultiVector> Xcopy;
490 double **xPtr = 0, **yPtr = 0;
491 Xcopy->ExtractView(&xPtr);
494 #ifdef HAVE_IFPACK_EPETRAEXT
495 EpetraExt_PointToBlockDiagPermute* IBD=0;
497 IBD = &*InvBlockDiagonal_;
506 #ifdef HAVE_IFPACK_EPETRAEXT
508 IBD->ApplyInverse(*Xcopy, Y);
512 double *yPointer = yPtr[0], *xPointer = xPtr[0];
513 for (
int i = 0; i < len; ++i)
514 yPointer[i] = xPointer[i] * invDiag[i];
517 for (
int i = 0; i < len; ++i) {
518 double coeff = invDiag[i];
519 for (
int k = 0; k < nVec; ++k)
520 yPtr[k][i] = xPtr[k][i] * coeff;
531 double delta = 2.0 / (beta - alpha);
532 double theta = 0.5 * (beta + alpha);
533 double s1 = theta * delta;
540 bool zeroOut =
false;
543 #ifdef HAVE_IFPACK_EPETRAEXT
547 double *vPointer = V.
Values(), *wPointer = W.Values();
549 double oneOverTheta = 1.0/theta;
563 #ifdef HAVE_IFPACK_EPETRAEXT
565 Temp.Update(oneOverTheta, X, -oneOverTheta, V, 0.0);
566 IBD->ApplyInverse(Temp, W);
571 IBD->ApplyInverse(W, Temp);
578 double *xPointer = xPtr[0];
579 for (
int i = 0; i < len; ++i)
580 wPointer[i] = invDiag[i] * (xPointer[i] - vPointer[i]) * oneOverTheta;
583 for (
int i = 0; i < len; ++i) {
584 double coeff = invDiag[i]*oneOverTheta;
585 double *wi = wPointer + i, *vi = vPointer + i;
586 for (
int k = 0; k < nVec; ++k) {
587 *wi = (xPtr[k][i] - (*vi)) * coeff;
588 wi = wi + len; vi = vi + len;
597 #ifdef HAVE_IFPACK_EPETRAEXT
599 IBD->ApplyInverse(X, W);
604 IBD->ApplyInverse(W, Temp);
608 W.Scale(oneOverTheta);
614 double *xPointer = xPtr[0];
615 for (
int i = 0; i < len; ++i)
616 wPointer[i] = invDiag[i] * xPointer[i] * oneOverTheta;
618 memcpy(yPtr[0], wPointer, len*
sizeof(
double));
621 for (
int i = 0; i < len; ++i) {
622 double coeff = invDiag[i]*oneOverTheta;
623 double *wi = wPointer + i;
624 for (
int k = 0; k < nVec; ++k) {
625 *wi = xPtr[k][i] * coeff;
630 for (
int k = 0; k < nVec; ++k)
631 memcpy(yPtr[k], wPointer + k*len, len*
sizeof(
double));
636 double rhok = 1.0/s1, rhokp1;
637 double dtemp1, dtemp2;
640 double *xPointer = xPtr[0];
641 for (
int k = 0; k < degreeMinusOne; ++k) {
643 rhokp1 = 1.0 / (2.0*s1 - rhok);
644 dtemp1 = rhokp1 * rhok;
645 dtemp2 = 2.0 * rhokp1 * delta;
652 #ifdef HAVE_IFPACK_EPETRAEXT
655 V.Update(dtemp2, X, -dtemp2);
656 IBD->ApplyInverse(V, Temp);
661 IBD->ApplyInverse(V, Temp);
665 W.Update(1.0, Temp, 1.0);
669 for (
int i = 0; i < len; ++i)
670 wPointer[i] += dtemp2* invDiag[i] * (xPointer[i] - vPointer[i]);
677 for (
int k = 0; k < degreeMinusOne; ++k) {
679 rhokp1 = 1.0 / (2.0*s1 - rhok);
680 dtemp1 = rhokp1 * rhok;
681 dtemp2 = 2.0 * rhokp1 * delta;
688 #ifdef HAVE_IFPACK_EPETRAEXT
691 V.Update(dtemp2, X, -dtemp2);
692 IBD->ApplyInverse(V, Temp);
697 IBD->ApplyInverse(V,Temp);
701 W.Update(1.0, Temp, 1.0);
705 for (
int i = 0; i < len; ++i) {
706 double coeff = invDiag[i]*dtemp2;
707 double *wi = wPointer + i, *vi = vPointer + i;
708 for (
int j = 0; j < nVec; ++j) {
709 *wi += (xPtr[j][i] - (*vi)) * coeff;
710 wi = wi + len; vi = vi + len;
731 const int MaximumIterations,
732 double& lambda_max,
const unsigned int * RngSeed)
736 double RQ_top, RQ_bottom, norm;
739 if(RngSeed) x.
SetSeed(*RngSeed);
746 for (
int iter = 0; iter < MaximumIterations; ++iter)
748 Operator.
Apply(x, y);
752 lambda_max = RQ_top / RQ_bottom;
765 const int MaximumIterations,
766 double& lambda_min,
double& lambda_max,
const unsigned int * RngSeed)
768 #ifdef HAVE_IFPACK_AZTECOO
771 if(RngSeed) x.
SetSeed(*RngSeed);
777 solver.SetAztecOption(AZ_solver, AZ_cg_condnum);
778 solver.SetAztecOption(AZ_output, AZ_none);
783 solver.SetPrecOperator(&diag);
784 solver.Iterate(MaximumIterations, 1e-10);
786 const double* status = solver.GetAztecStatus();
788 lambda_min = status[AZ_lambda_min];
789 lambda_max = status[AZ_lambda_max];
796 cout <<
"You need to configure IFPACK with support for AztecOO" << endl;
797 cout <<
"to use the CG estimator. This may require --enable-aztecoo" << endl;
798 cout <<
"in your configure script." << endl;
804 #ifdef HAVE_IFPACK_EPETRAEXT
806 PowerMethod(
const int MaximumIterations,
double& lambda_max,
const unsigned int * RngSeed)
812 double RQ_top, RQ_bottom, norm;
816 if(RngSeed) x.
SetSeed(*RngSeed);
823 for (
int iter = 0; iter < MaximumIterations; ++iter)
826 InvBlockDiagonal_->ApplyInverse(z,y);
828 InvBlockDiagonal_->ApplyInverse(y,z);
834 lambda_max = RQ_top / RQ_bottom;
845 #ifdef HAVE_IFPACK_EPETRAEXT
847 CG(
const int MaximumIterations,
848 double& lambda_min,
double& lambda_max,
const unsigned int * RngSeed)
858 #ifdef HAVE_IFPACK_AZTECOO
861 if(RngSeed) x.
SetSeed(*RngSeed);
867 solver.SetAztecOption(AZ_solver, AZ_cg_condnum);
868 solver.SetAztecOption(AZ_output, AZ_none);
870 solver.SetPrecOperator(&*InvBlockDiagonal_);
871 solver.Iterate(MaximumIterations, 1e-10);
873 const double* status = solver.GetAztecStatus();
875 lambda_min = status[AZ_lambda_min];
876 lambda_max = status[AZ_lambda_max];
883 cout <<
"You need to configure IFPACK with support for AztecOO" << endl;
884 cout <<
"to use the CG estimator. This may require --enable-aztecoo" << endl;
885 cout <<
"in your configure script." << endl;
891 #endif // HAVE_IFPACK_EPETRAEXT