int powerMethod (double & lambda, Epetra_CrsMatrix& A, const int niters, const double tolerance, const bool verbose) { // In the power iteration, z = A*q. Thus, q must be in the domain // of A, and z must be in the range of A. The residual vector is of // course in the range of A. Epetra_Vector q (A.OperatorDomainMap ()); Epetra_Vector z (A.OperatorRangeMap ()); Epetra_Vector resid (A.OperatorRangeMap ()); Epetra_Flops* counter = A.GetFlopCounter(); if (counter != 0) { q.SetFlopCounter(A); z.SetFlopCounter(A); resid.SetFlopCounter(A); } // Initialize the starting vector z with random data. z.Random(); double normz, residual; int ierr = 1; for (int iter = 0; iter < niters; ++iter) { z.Norm2 (&normz); // normz := ||z||_2 q.Scale (1.0/normz, z); // q := z / normz A.Multiply(false, q, z); // z := A * q q.Dot(z, &lambda); // lambda := dot (q, z) // Compute the residual vector and display status output every // 100 iterations, or if we have reached the maximum number of // iterations. if (iter % 100 == 0 || iter + 1 == niters) { resid.Update (1.0, z, -lambda, q, 0.0); // resid := A*q - lambda*q resid.Norm2 (&residual); // residual := ||resid||_2 if (verbose) cout << "Iter = " << iter << " Lambda = " << lambda << " Residual of A*q - lambda*q = " << residual << endl; } if (residual < tolerance) { // We've converged! ierr = 0; break; } } return ierr; }
int power_method(Epetra_CrsMatrix& A, double &lambda, int niters, double tolerance, bool verbose) { Epetra_Vector q(A.RowMap()); Epetra_Vector z(A.RowMap()); Epetra_Vector resid(A.RowMap()); Epetra_Flops * counter = A.GetFlopCounter(); if (counter!=0) { q.SetFlopCounter(A); z.SetFlopCounter(A); resid.SetFlopCounter(A); } // Fill z with random Numbers z.Random(); // variable needed for iteration double normz, residual; int ierr = 1; for (int iter = 0; iter < niters; iter++) { z.Norm2(&normz); // Compute 2-norm of z q.Scale(1.0/normz, z); A.Multiply(false, q, z); // Compute z = A*q q.Dot(z, &lambda); // Approximate maximum eigenvalue if (iter%100==0 || iter+1==niters) { resid.Update(1.0, z, -lambda, q, 0.0); // Compute A*q - lambda*q resid.Norm2(&residual); if (verbose) cout << "Iter = " << iter << " Lambda = " << lambda << " Residual of A*q - lambda*q = " << residual << endl; } if (residual < tolerance) { ierr = 0; break; } } return(ierr); }
int invIteration(Epetra_CrsMatrix& A, double &lambda, bool verbose) { Ifpack_CrsRiluk * M; applyInverseSetup(A, M); Epetra_Vector q(A.RowMap()); Epetra_Vector z(A.RowMap()); Epetra_Vector resid(A.RowMap()); Epetra_Flops * counter = A.GetFlopCounter(); if (counter!=0) { q.SetFlopCounter(A); z.SetFlopCounter(A); resid.SetFlopCounter(A); } // Fill z with random Numbers z.Random(); // variable needed for iteration double normz, residual; int niters = 100; double tolerance = 1.0E-6; int ierr = 1; for (int iter = 0; iter < niters; iter++) { if (verbose) cout << endl << " ***** Performing step " << iter << " of inverse iteration ***** " << endl; z.Norm2(&normz); // Compute 2-norm of z q.Scale(1.0/normz, z); applyInverse(A, z, q, M, verbose); // Compute z such that Az = q q.Dot(z, &lambda); // Approximate maximum eigenvalue if (iter%10==0 || iter+1==niters) { resid.Update(1.0, z, -lambda, q, 0.0); // Compute A(inv)*q - lambda*q resid.Norm2(&residual); cout << endl << "***** Inverse Iteration Step " << iter+1 << endl << " Lambda = " << 1.0/lambda << endl << " Residual of A(inv)*q - lambda*q = " << residual << endl; } if (residual < tolerance) { ierr = 0; break; } } // lambda is the largest eigenvalue of A(inv). 1/lambda is smallest eigenvalue of A. lambda = 1.0/lambda; // Compute A*q - lambda*q explicitly A.Multiply(false, q, z); resid.Update(1.0, z, -lambda, q, 0.0); // Compute A*q - lambda*q resid.Norm2(&residual); cout << " Explicitly computed residual of A*q - lambda*q = " << residual << endl; applyInverseDestroy(M); return(ierr); }