NOX::Abstract::Group::ReturnType LOCA::EigenvalueSort::LargestMagnitude::sort(int n, double* r_evals, double* i_evals, std::vector<int>* perm) const { int i, j; int tempord = 0; double temp, tempr, tempi; Teuchos::LAPACK<int,double> lapack; // // Reset the index if (perm) { for (i=0; i < n; i++) { (*perm)[i] = i; } } //--------------------------------------------------------------- // Sort eigenvalues in decreasing order of magnitude //--------------------------------------------------------------- for (j=1; j < n; ++j) { tempr = r_evals[j]; tempi = i_evals[j]; if (perm) tempord = (*perm)[j]; temp=lapack.LAPY2(r_evals[j],i_evals[j]); for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i])<temp; --i) { r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; if (perm) (*perm)[i+1]=(*perm)[i]; } r_evals[i+1] = tempr; i_evals[i+1] = tempi; if (perm) (*perm)[i+1] = tempord; } return NOX::Abstract::Group::Ok; }
// *********************************************************** int DG_Prob::Eigenvectors(const double Dt, const Epetra_Map & Map) { printf("Entrou em Eigenvectors\n"); #ifdef HAVE_MPI Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif //MPI::COMM_WORLD.Barrier(); Comm.Barrier(); Teuchos::RCP<Epetra_FECrsMatrix> M = Teuchos::rcp(new Epetra_FECrsMatrix(Copy, Map,0));//&NNz[0]); Teuchos::RCP<Epetra_FEVector> RHS = Teuchos::rcp(new Epetra_FEVector(Map,1)); DG_MatrizVetor_Epetra(Dt,M,RHS); Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp(new Epetra_CrsMatrix(Copy, Map,0 /* &NNz[0]*/) ); Epetra_Export Exporter(Map,Map); A->PutScalar(0.0); A->Export(*(M.ptr()),Exporter,Add); A->FillComplete(); using std::cout; // int nx = 5; bool boolret; int MyPID = Comm.MyPID(); bool verbose = true; bool debug = false; std::string which("LR"); Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","nodebug",&debug,"Print debugging information."); cmdp.setOption("sort",&which,"Targetted eigenvalues (SM,LM,SR,LR,SI,or LI)."); typedef double ScalarType; typedef Teuchos::ScalarTraits<ScalarType> SCT; typedef SCT::magnitudeType MagnitudeType; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<ScalarType,MV> MVT; typedef Anasazi::OperatorTraits<ScalarType,MV,OP> OPT; // double rho = 2*nx+1; // Compute coefficients for discrete convection-diffution operator // const double one = 1.0; // int NumEntries, info; //************************************ // Start the block Arnoldi iteration //*********************************** // // Variables used for the Block Krylov Schur Method // int nev = 10; int blockSize = 1; int numBlocks = 20; int maxRestarts = 500; //int stepSize = 5; double tol = 1e-8; // Create a sort manager to pass into the block Krylov-Schur solver manager // --> Make sure the reference-counted pointer is of type Anasazi::SortManager<> // --> The block Krylov-Schur solver manager uses Anasazi::BasicSort<> by default, // so you can also pass in the parameter "Which", instead of a sort manager. Teuchos::RCP<Anasazi::SortManager<MagnitudeType> > MySort = Teuchos::rcp( new Anasazi::BasicSort<MagnitudeType>( which ) ); // Set verbosity level int verbosity = Anasazi::Errors + Anasazi::Warnings; if (verbose) { verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails; } if (debug) { verbosity += Anasazi::Debug; } // // Create parameter list to pass into solver manager // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Sort Manager", MySort ); //MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Num Blocks", numBlocks ); MyPL.set( "Maximum Restarts", maxRestarts ); //MyPL.set( "Step Size", stepSize ); MyPL.set( "Convergence Tolerance", tol ); // Create an Epetra_MultiVector for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(Map, blockSize) ); ivec->Random(); // Create the eigenproblem. Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(A, ivec) ); // Inform the eigenproblem that the operator A is symmetric //MyProblem->setHermitian(rho==0.0); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finishing passing it information boolret = MyProblem->setProblem(); if (boolret != true) { if (verbose && MyPID == 0) { cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::BlockKrylovSchurSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); if (returnCode != Anasazi::Converged && MyPID==0 && verbose) { cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << endl; } // Get the Ritz values from the eigensolver std::vector<Anasazi::Value<double> > ritzValues = MySolverMgr.getRitzValues(); // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { int numritz = (int)ritzValues.size(); cout.setf(std::ios_base::right, std::ios_base::adjustfield); cout<<endl<< "Computed Ritz Values"<< endl; if (MyProblem->isHermitian()) { cout<< std::setw(16) << "Real Part" << endl; cout<<"-----------------------------------------------------------"<<endl; for (int i=0; i<numritz; i++) { cout<< std::setw(16) << ritzValues[i].realpart << endl; } cout<<"-----------------------------------------------------------"<<endl; } else { cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << endl; cout<<"-----------------------------------------------------------"<<endl; for (int i=0; i<numritz; i++) { cout<< std::setw(16) << ritzValues[i].realpart << std::setw(16) << ritzValues[i].imagpart << endl; } cout<<"-----------------------------------------------------------"<<endl; } } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<ScalarType,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<ScalarType> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; std::vector<int> index = sol.index; int numev = sol.numVecs; if (numev > 0) { // Compute residuals. Teuchos::LAPACK<int,double> lapack; std::vector<double> normA(numev); if (MyProblem->isHermitian()) { // Get storage Epetra_MultiVector Aevecs(Map,numev); Teuchos::SerialDenseMatrix<int,double> B(numev,numev); B.putScalar(0.0); for (int i=0; i<numev; i++) {B(i,i) = evals[i].realpart;} // Compute A*evecs OPT::Apply( *A, *evecs, Aevecs ); // Compute A*evecs - lambda*evecs and its norm MVT::MvTimesMatAddMv( -1.0, *evecs, B, 1.0, Aevecs ); MVT::MvNorm( Aevecs, normA ); // Scale the norms by the eigenvalue for (int i=0; i<numev; i++) { normA[i] /= Teuchos::ScalarTraits<double>::magnitude( evals[i].realpart ); } } else { // The problem is non-Hermitian. int i=0; std::vector<int> curind(1); std::vector<double> resnorm(1), tempnrm(1); Teuchos::RCP<MV> tempAevec; Teuchos::RCP<const MV> evecr, eveci; Epetra_MultiVector Aevec(Map,numev); // Compute A*evecs OPT::Apply( *A, *evecs, Aevec ); Teuchos::SerialDenseMatrix<int,double> Breal(1,1), Bimag(1,1); while (i<numev) { if (index[i]==0) { // Get a view of the current eigenvector (evecr) curind[0] = i; evecr = MVT::CloneView( *evecs, curind ); // Get a copy of A*evecr tempAevec = MVT::CloneCopy( Aevec, curind ); // Compute A*evecr - lambda*evecr Breal(0,0) = evals[i].realpart; MVT::MvTimesMatAddMv( -1.0, *evecr, Breal, 1.0, *tempAevec ); // Compute the norm of the residual and increment counter MVT::MvNorm( *tempAevec, resnorm ); normA[i] = resnorm[0]/Teuchos::ScalarTraits<MagnitudeType>::magnitude( evals[i].realpart ); i++; } else { // Get a view of the real part of the eigenvector (evecr) curind[0] = i; evecr = MVT::CloneView( *evecs, curind ); // Get a copy of A*evecr tempAevec = MVT::CloneCopy( Aevec, curind ); // Get a view of the imaginary part of the eigenvector (eveci) curind[0] = i+1; eveci = MVT::CloneView( *evecs, curind ); // Set the eigenvalue into Breal and Bimag Breal(0,0) = evals[i].realpart; Bimag(0,0) = evals[i].imagpart; // Compute A*evecr - evecr*lambdar + eveci*lambdai MVT::MvTimesMatAddMv( -1.0, *evecr, Breal, 1.0, *tempAevec ); MVT::MvTimesMatAddMv( 1.0, *eveci, Bimag, 1.0, *tempAevec ); MVT::MvNorm( *tempAevec, tempnrm ); // Get a copy of A*eveci tempAevec = MVT::CloneCopy( Aevec, curind ); // Compute A*eveci - eveci*lambdar - evecr*lambdai MVT::MvTimesMatAddMv( -1.0, *evecr, Bimag, 1.0, *tempAevec ); MVT::MvTimesMatAddMv( -1.0, *eveci, Breal, 1.0, *tempAevec ); MVT::MvNorm( *tempAevec, resnorm ); // Compute the norms and scale by magnitude of eigenvalue normA[i] = lapack.LAPY2( tempnrm[i], resnorm[i] ) / lapack.LAPY2( evals[i].realpart, evals[i].imagpart ); normA[i+1] = normA[i]; i=i+2; } } } // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { cout.setf(std::ios_base::right, std::ios_base::adjustfield); cout<<endl<< "Actual Residuals"<<endl; if (MyProblem->isHermitian()) { cout<< std::setw(16) << "Real Part" << std::setw(20) << "Direct Residual"<< endl; cout<<"-----------------------------------------------------------"<<endl; for (int i=0; i<numev; i++) { cout<< std::setw(16) << evals[i].realpart << std::setw(20) << normA[i] << endl; } cout<<"-----------------------------------------------------------"<<endl; } else { cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::setw(20) << "Direct Residual"<< endl; cout<<"-----------------------------------------------------------"<<endl; for (int i=0; i<numev; i++) { cout<< std::setw(16) << evals[i].realpart << std::setw(16) << evals[i].imagpart << std::setw(20) << normA[i] << endl; } cout<<"-----------------------------------------------------------"<<endl; } } } #ifdef EPETRA_MPI MPI_Finalize(); #endif return 0; }
int main(int argc, char *argv[]) { #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm(MPI_COMM_WORLD); #else Epetra_SerialComm Comm; #endif bool testFailed; bool boolret; int MyPID = Comm.MyPID(); bool verbose = true; bool debug = false; std::string which("SM"); Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","nodebug",&debug,"Print debugging information."); cmdp.setOption("sort",&which,"Targetted eigenvalues (SM,LM,SR,LR,SI,or LI)."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } typedef double ScalarType; typedef Teuchos::ScalarTraits<ScalarType> ScalarTypeTraits; typedef ScalarTypeTraits::magnitudeType MagnitudeType; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<ScalarType,MV> MVTraits; typedef Anasazi::OperatorTraits<ScalarType,MV,OP> OpTraits; // Dimension of the matrix int nx = 10; // Discretization points in any one direction. int NumGlobalElements = nx*nx; // Size of matrix nx*nx // Construct a Map that puts approximately the same number of // equations on each processor. Epetra_Map Map(NumGlobalElements, 0, Comm); // Get update list and number of local equations from newly created Map. int NumMyElements = Map.NumMyElements(); std::vector<int> MyGlobalElements(NumMyElements); Map.MyGlobalElements(&MyGlobalElements[0]); // Create an integer vector NumNz that is used to build the Petra Matrix. // NumNz[i] is the Number of OFF-DIAGONAL term for the ith global equation // on this processor std::vector<int> NumNz(NumMyElements); /* We are building a matrix of block structure: | T -I | |-I T -I | | -I T | | ... -I| | -I T| where each block is dimension nx by nx and the matrix is on the order of nx*nx. The block T is a tridiagonal matrix. */ for (int i=0; i<NumMyElements; i++) { if (MyGlobalElements[i] == 0 || MyGlobalElements[i] == NumGlobalElements-1 || MyGlobalElements[i] == nx-1 || MyGlobalElements[i] == nx*(nx-1) ) { NumNz[i] = 3; } else if (MyGlobalElements[i] < nx || MyGlobalElements[i] > nx*(nx-1) || MyGlobalElements[i]%nx == 0 || (MyGlobalElements[i]+1)%nx == 0) { NumNz[i] = 4; } else { NumNz[i] = 5; } } // Create an Epetra_Matrix Teuchos::RCP<Epetra_CrsMatrix> A = Teuchos::rcp( new Epetra_CrsMatrix(Copy, Map, &NumNz[0]) ); // Diffusion coefficient, can be set by user. // When rho*h/2 <= 1, the discrete convection-diffusion operator has real eigenvalues. // When rho*h/2 > 1, the operator has complex eigenvalues. double rho = 2*(nx+1); // Compute coefficients for discrete convection-diffution operator const double one = 1.0; std::vector<double> Values(4); std::vector<int> Indices(4); double h = one /(nx+1); double h2 = h*h; double c = 5.0e-01*rho/ h; Values[0] = -one/h2 - c; Values[1] = -one/h2 + c; Values[2] = -one/h2; Values[3]= -one/h2; double diag = 4.0 / h2; int NumEntries, info; for (int i=0; i<NumMyElements; i++) { if (MyGlobalElements[i]==0) { Indices[0] = 1; Indices[1] = nx; NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == nx*(nx-1)) { Indices[0] = nx*(nx-1)+1; Indices[1] = nx*(nx-2); NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == nx-1) { Indices[0] = nx-2; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); Indices[0] = 2*nx-1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] == NumGlobalElements-1) { Indices[0] = NumGlobalElements-2; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); Indices[0] = nx*(nx-1)-1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] < nx) { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]+nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i] > nx*(nx-1)) { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]-nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else if (MyGlobalElements[i]%nx == 0) { Indices[0] = MyGlobalElements[i]+1; Indices[1] = MyGlobalElements[i]-nx; Indices[2] = MyGlobalElements[i]+nx; NumEntries = 3; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[1], &Indices[0]); assert( info==0 ); } else if ((MyGlobalElements[i]+1)%nx == 0) { Indices[0] = MyGlobalElements[i]-nx; Indices[1] = MyGlobalElements[i]+nx; NumEntries = 2; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[2], &Indices[0]); assert( info==0 ); Indices[0] = MyGlobalElements[i]-1; NumEntries = 1; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } else { Indices[0] = MyGlobalElements[i]-1; Indices[1] = MyGlobalElements[i]+1; Indices[2] = MyGlobalElements[i]-nx; Indices[3] = MyGlobalElements[i]+nx; NumEntries = 4; info = A->InsertGlobalValues(MyGlobalElements[i], NumEntries, &Values[0], &Indices[0]); assert( info==0 ); } // Put in the diagonal entry info = A->InsertGlobalValues(MyGlobalElements[i], 1, &diag, &MyGlobalElements[i]); assert( info==0 ); } // Finish up info = A->FillComplete(); assert( info==0 ); A->SetTracebackMode(1); // Shutdown Epetra Warning tracebacks //************************************ // Start the block Davidson iteration //*********************************** // // Variables used for the Generalized Davidson Method // int nev = 4; int blockSize = 1; int maxDim = 50; int restartDim = 10; int maxRestarts = 500; double tol = 1e-10; // Set verbosity level int verbosity = Anasazi::Errors + Anasazi::Warnings; if (verbose) { verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails; } if (debug) { verbosity += Anasazi::Debug; } // // Create parameter list to pass into solver manager // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Maximum Subspace Dimension", maxDim); MyPL.set( "Restart Dimension", restartDim); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); MyPL.set( "Relative Convergence Tolerance", true ); MyPL.set( "Initial Guess", "User" ); // Create an Epetra_MultiVector for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(Map, blockSize) ); ivec->Random(); // Create the eigenproblem. Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double,MV,OP>() ); MyProblem->setA(A); MyProblem->setInitVec(ivec); // Inform the eigenproblem that the operator A is non-Hermitian MyProblem->setHermitian(false); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finishing passing it information boolret = MyProblem->setProblem(); if (boolret != true) { if (verbose && MyPID == 0) { std::cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << std::endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::GeneralizedDavidsonSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); testFailed = false; if (returnCode != Anasazi::Converged && MyPID==0 && verbose) { testFailed = true; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<ScalarType,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<ScalarType> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; std::vector<int> index = sol.index; int numev = sol.numVecs; // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { int numritz = (int)evals.size(); std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<std::endl<< "Computed Ritz Values"<< std::endl; std::cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::endl; std::cout<<"-----------------------------------------------------------"<<std::endl; for (int i=0; i<numritz; i++) { std::cout<< std::setw(16) << evals[i].realpart << std::setw(16) << evals[i].imagpart << std::endl; } std::cout<<"-----------------------------------------------------------"<<std::endl; } if (numev > 0) { // Compute residuals. Teuchos::LAPACK<int,double> lapack; std::vector<double> normA(numev); // The problem is non-Hermitian. int i=0; std::vector<int> curind(1); std::vector<double> resnorm(1), tempnrm(1); Teuchos::RCP<MV> tempAevec; Teuchos::RCP<const MV> evecr, eveci; Epetra_MultiVector Aevec(Map,numev); // Compute A*evecs OpTraits::Apply( *A, *evecs, Aevec ); Teuchos::SerialDenseMatrix<int,double> Breal(1,1), Bimag(1,1); while (i<numev) { if (index[i]==0) { // Get a view of the current eigenvector (evecr) curind[0] = i; evecr = MVTraits::CloneView( *evecs, curind ); // Get a copy of A*evecr tempAevec = MVTraits::CloneCopy( Aevec, curind ); // Compute A*evecr - lambda*evecr Breal(0,0) = evals[i].realpart; MVTraits::MvTimesMatAddMv( -1.0, *evecr, Breal, 1.0, *tempAevec ); // Compute the norm of the residual and increment counter MVTraits::MvNorm( *tempAevec, resnorm ); normA[i] = resnorm[0] / Teuchos::ScalarTraits<MagnitudeType>::magnitude( evals[i].realpart ); i++; } else { // Get a view of the real part of the eigenvector (evecr) curind[0] = i; evecr = MVTraits::CloneView( *evecs, curind ); // Get a copy of A*evecr tempAevec = MVTraits::CloneCopy( Aevec, curind ); // Get a view of the imaginary part of the eigenvector (eveci) curind[0] = i+1; eveci = MVTraits::CloneView( *evecs, curind ); // Set the eigenvalue into Breal and Bimag Breal(0,0) = evals[i].realpart; Bimag(0,0) = evals[i].imagpart; // Compute A*evecr - evecr*lambdar + eveci*lambdai MVTraits::MvTimesMatAddMv( -1.0, *evecr, Breal, 1.0, *tempAevec ); MVTraits::MvTimesMatAddMv( 1.0, *eveci, Bimag, 1.0, *tempAevec ); MVTraits::MvNorm( *tempAevec, tempnrm ); // Get a copy of A*eveci tempAevec = MVTraits::CloneCopy( Aevec, curind ); // Compute A*eveci - eveci*lambdar - evecr*lambdai MVTraits::MvTimesMatAddMv( -1.0, *evecr, Bimag, 1.0, *tempAevec ); MVTraits::MvTimesMatAddMv( -1.0, *eveci, Breal, 1.0, *tempAevec ); MVTraits::MvNorm( *tempAevec, resnorm ); // Compute the norms and scale by magnitude of eigenvalue normA[i] = lapack.LAPY2( tempnrm[0], resnorm[0] ) / lapack.LAPY2( evals[i].realpart, evals[i].imagpart ); normA[i+1] = normA[i]; i=i+2; } } // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { std::cout.setf(std::ios_base::right, std::ios_base::adjustfield); std::cout<<std::endl<< "Actual Residuals"<<std::endl; std::cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::setw(20) << "Direct Residual"<< std::endl; std::cout<<"-----------------------------------------------------------"<<std::endl; for (int j=0; j<numev; j++) { std::cout<< std::setw(16) << evals[j].realpart << std::setw(16) << evals[j].imagpart << std::setw(20) << normA[j] << std::endl; if ( normA[j] > tol ) { testFailed = true; } } std::cout<<"-----------------------------------------------------------"<<std::endl; } } #ifdef EPETRA_MPI MPI_Finalize(); #endif if (testFailed) { if (verbose && MyPID==0) { std::cout << "End Result: TEST FAILED" << std::endl; } return -1; } // // Default return value // if (verbose && MyPID==0) { std::cout << "End Result: TEST PASSED" << std::endl; } return 0; }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpisess(&argc,&argv,&cout); bool run_me = (mpisess.getRank() == 0); bool testFailed = false; if (run_me) { try { // useful typedefs typedef double ST; typedef Teuchos::ScalarTraits<ST> STT; typedef STT::magnitudeType MT; typedef Teuchos::ScalarTraits<MT> MTT; typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<ST,MV> MVT; typedef Anasazi::OperatorTraits<ST,MV,OP> OPT; // parse here, so everyone knows about failure bool verbose = false; bool debug = false; std::string k_filename = "linearized_qevp_A.hb"; std::string m_filename = "linearized_qevp_B.hb"; int blockSize = 1; int numBlocks = 30; int nev = 20; int maxRestarts = 0; int extraBlocks = 0; int stepSize = 1; int numPrint = 536; MT tol = 1e-8; Teuchos::CommandLineProcessor cmdp(true,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("debug","normal",&debug,"Print debugging information."); cmdp.setOption("A-filename",&k_filename,"Filename and path of the stiffness matrix."); cmdp.setOption("B-filename",&m_filename,"Filename and path of the mass matrix."); cmdp.setOption("extra-blocks",&extraBlocks,"Extra blocks to keep on a restart."); cmdp.setOption("block-size",&blockSize,"Block size."); cmdp.setOption("num-blocks",&numBlocks,"Number of blocks in Krylov basis."); cmdp.setOption("step-size",&stepSize,"Step size."); cmdp.setOption("nev",&nev,"Number of eigenvalues to compute."); cmdp.setOption("num-restarts",&maxRestarts,"Maximum number of restarts."); cmdp.setOption("tol",&tol,"Convergence tolerance."); cmdp.setOption("num-print",&numPrint,"Number of Ritz values to print."); // parse() will throw an exception on error cmdp.parse(argc,argv); // Get the stiffness and mass matrices Epetra_SerialComm Comm; RCP<Epetra_Map> Map; RCP<Epetra_CrsMatrix> A, B; EpetraExt::readEpetraLinearSystem( k_filename, Comm, &A, &Map ); EpetraExt::readEpetraLinearSystem( m_filename, Comm, &B, &Map ); // // ******************************************************* // Set up Amesos direct solver for inner iteration // ******************************************************* // // Create Epetra linear problem class to solve "Kx = b" Epetra_LinearProblem AmesosProblem; AmesosProblem.SetOperator(A.get()); // Create Amesos factory and solver for solving "Kx = b" using a direct factorization Amesos amesosFactory; RCP<Amesos_BaseSolver> AmesosSolver = rcp( amesosFactory.Create( "Klu", AmesosProblem ) ); // The AmesosGenOp class assumes that the symbolic/numeric factorizations have already // been performed on the linear problem. AmesosSolver->SymbolicFactorization(); AmesosSolver->NumericFactorization(); // // ************************************ // Start the block Arnoldi iteration // ************************************ // // Variables used for the Block Arnoldi Method // int verbosity = Anasazi::Errors + Anasazi::Warnings + Anasazi::FinalSummary; if (verbose) { verbosity += Anasazi::IterationDetails; } if (debug) { verbosity += Anasazi::Debug; } // // Create parameter list to pass into solver // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", "LM" ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Num Blocks", numBlocks ); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); MyPL.set( "Step Size", stepSize ); MyPL.set( "Extra NEV Blocks", extraBlocks ); MyPL.set( "Print Number of Ritz Values", numPrint ); // Create an Epetra_MultiVector for an initial vector to start the solver. // Note: This needs to have the same number of columns as the blocksize. RCP<Epetra_MultiVector> ivec = rcp( new Epetra_MultiVector(A->Map(), blockSize) ); // MVT::MvRandom( *ivec ); // FINISH: put this back in MVT::MvInit(*ivec,1.0); // Create the Epetra_Operator for the spectral transformation using the Amesos direct solver. RCP<AmesosGenOp> Aop = rcp( new AmesosGenOp(AmesosProblem, AmesosSolver, B) ); // standard inner product; B is not symmetric positive definite, and Op has no symmetry. RCP<Anasazi::BasicEigenproblem<ST,MV,OP> > MyProblem = rcp( new Anasazi::BasicEigenproblem<ST,MV,OP>(Aop, ivec) ); MyProblem->setHermitian(false); MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finished passing it information TEUCHOS_TEST_FOR_EXCEPTION( MyProblem->setProblem() != true, std::runtime_error, "Anasazi::BasicEigenproblem::setProblem() returned with error."); // Initialize the Block Arnoldi solver Anasazi::BlockKrylovSchurSolMgr<ST,MV,OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<ST,MV> sol = MyProblem->getSolution(); vector<Anasazi::Value<ST> > evals = sol.Evals; RCP<MV> evecs = sol.Evecs; vector<int> index = sol.index; int numev = sol.numVecs; if (returnCode != Anasazi::Converged) { cout << "Anasazi::EigensolverMgr::solve() returned unconverged, computing " << numev << " of " << nev << endl; } else { cout << "Anasazi::EigensolverMgr::solve() returned converged, computing " << numev << " of " << nev << endl; } if (numev > 0) { // Compute residuals. Teuchos::LAPACK<int,MT> lapack; vector<MT> normA(numev); // Back-transform the eigenvalues for (int i=0; i<numev; ++i) { MT mag2 = lapack.LAPY2(evals[i].realpart,evals[i].imagpart); mag2 = mag2*mag2; evals[i].realpart /= mag2; evals[i].imagpart /= (-mag2); } // The problem is non-Hermitian. vector<int> curind(1); vector<MT> resnorm(1), tempnrm(1); Teuchos::RCP<const MV> Av_r, Av_i, Bv_r, Bv_i; Epetra_MultiVector Aevec(*Map,numev), Bevec(*Map,numev), res(*Map,1); // Compute A*evecs, B*evecs OPT::Apply( *A, *evecs, Aevec ); OPT::Apply( *B, *evecs, Bevec ); for (int i=0; i<numev;) { if (index[i]==0) { // Get views of the real part of A*evec,B*evec curind[0] = i; Av_r = MVT::CloneView( Aevec, curind ); Bv_r = MVT::CloneView( Bevec, curind ); // Compute set res = lambda*B*evec - A*evec // eigenvalue and eigenvector are both real MVT::MvAddMv(evals[i].realpart,*Bv_r,-1.0,*Av_r,res); // Compute the norm of the residual and increment counter MVT::MvNorm( res, resnorm ); // Scale the residual normA[i] = resnorm[0]; MT mag = MTT::magnitude(evals[i].realpart); if ( mag > MTT::one() ) { normA[i] /= mag; } // done with this eigenvector i++; } else { // Get a copy of A*evec, B*evec curind[0] = i; Av_r = MVT::CloneCopy( Aevec, curind ); Bv_r = MVT::CloneView( Bevec, curind ); // Get the imaginary part of A*evec,B*evec curind[0] = i+1; Av_i = MVT::CloneCopy( Aevec, curind ); Bv_i = MVT::CloneView( Bevec, curind ); // grab temp copies of the eigenvalue MT l_r = evals[i].realpart, l_i = evals[i].imagpart; // Compute real part of B*evec*lambda - A*evec // B is real // evec = evec_r + evec_i*i // lambda = lambda_r + lambda_i*i // // evec*lambda = evec_r*lambda_r - evec_i*lambda_i + evec_r*lambda_i*i + evec_i*lambda_r*i // // res = B*evec*lambda - A*evec // = B*(evec_r*lambda_r - evec_i*lambda_i + evec_r*lambda_i*i + evec_i*lambda_r*i) - A*evec_r - A*evec_i*i // = (B*evec_r*lambda_r - B*evec_i*lambda_i - A*evec_r) + (B*evec_r*lambda_i + B*evec_i*lambda_r - A*evec_i)*i // real(res) = B*evec_r*lambda_r - B*evec_i*lambda_i - A*evec_r // imag(res) = B*evec_r*lambda_i + B*evec_i*lambda_r - A*evec_i // compute real part of residual and its norm MVT::MvAddMv(l_r,*Bv_r, -l_i,*Bv_i, res); MVT::MvAddMv(MTT::one(),res, -MTT::one(),*Av_r, res); MVT::MvNorm(res,tempnrm); // compute imag part of residual and its norm MVT::MvAddMv(l_i,*Bv_r, l_r,*Bv_i, res); MVT::MvAddMv(MTT::one(),res, -MTT::one(),*Av_i, res); MVT::MvNorm(res,resnorm); // Compute the norms and scale by magnitude of eigenvalue normA[i] = lapack.LAPY2( tempnrm[0], resnorm[0] ); MT mag = lapack.LAPY2(evals[i].realpart, evals[i].imagpart); if (mag > MTT::one()) { normA[i] /= mag; } normA[i+1] = normA[i]; // done with this conjugate pair i=i+2; } } // Output computed eigenvalues and their direct residuals cout.setf(std::ios_base::right, std::ios_base::adjustfield); cout<<endl<< "Actual Residuals"<<endl; cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::setw(20) << "Direct Residual"<< endl; cout<<"-----------------------------------------------------------"<<endl; for (int j=0; j<numev; j++) { cout<< std::setw(16) << evals[j].realpart << std::setw(16) << evals[j].imagpart << std::setw(20) << normA[j] << endl; if (normA[j] > tol) { testFailed = true; } } cout<<"-----------------------------------------------------------"<<endl; } } catch (std::exception &e) { cout << "Caught exception: " << endl << e.what() << endl; testFailed = true; } } else { // run_me == false cout << "\nNot running on processor " << mpisess.getRank() << ". Serial problem only." << endl; } if (mpisess.getRank() == 0) { if (testFailed) { cout << "End Result: TEST FAILED" << endl; } else { cout << "End Result: TEST PASSED" << endl; } } return 0; }
int main(int argc, char *argv[]) { using std::cout; // bool haveM = false; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif int MyPID = Comm.MyPID(); bool verbose=false; bool isHermitian=false; std::string k_filename = ""; std::string m_filename = ""; std::string which = "SM"; Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("hermitian","non-hermitian",&isHermitian,"The eigenproblem being read in is Hermitian."); cmdp.setOption("sort",&which,"Targetted eigenvalues (SM,LM,SR,or LR)."); cmdp.setOption("K-filename",&k_filename,"Filename and path of the stiffness matrix."); cmdp.setOption("M-filename",&m_filename,"Filename and path of the mass matrix."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } // //********************************************************************** //******************Set up the problem to be solved********************* //********************************************************************** // // *****Read in matrix from file****** // Teuchos::RCP<Epetra_Map> Map; Teuchos::RCP<Epetra_CrsMatrix> K, M; EpetraExt::readEpetraLinearSystem( k_filename, Comm, &K, &Map ); { string testFile = "/tmp/test.mtx"; EpetraExt::RowMatrixToMatrixMarketFile(testFile.c_str(),*K); } if (haveM) { EpetraExt::readEpetraLinearSystem( m_filename, Comm, &M, &Map ); } // //************************************ // Start the block Arnoldi iteration //*********************************** // // Variables used for the Block Arnoldi Method // int nev = 1; int blockSize = 10; // int nevBlocks; // if (nev%blockSize) { // nevBlocks = nev/blockSize + 1; // } else { // nevBlocks = nev/blockSize; // } int numBlocks = 4; int maxRestarts = 10000; int step = 10; double tol = 1.0e-12; // Set verbosity level int verbosity = Anasazi::Errors + Anasazi::Warnings; if (verbose) { verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails; } // // Create parameter list to pass into solver // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Num Blocks", numBlocks ); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); MyPL.set( "Step Size", step ); typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<double, MV> MVT; typedef Anasazi::OperatorTraits<double, MV, OP> OPT; // // Create the eigenproblem to be solved. // Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(*Map, blockSize) ); ivec->Random(); Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem; if (haveM) { MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(K, M, ivec) ); } else { MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(K, ivec) ); } // Inform the eigenproblem that the (K,M) is Hermitian MyProblem->setHermitian( isHermitian ); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finished passing it information bool boolret = MyProblem->setProblem(); if (boolret != true) { if (verbose && MyPID == 0) { cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::BlockKrylovSchurSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); if (returnCode != Anasazi::Converged && MyPID==0 && verbose) { cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << endl; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<double,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<double> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; std::vector<int> index = sol.index; int numev = sol.numVecs; if (numev > 0) { // Compute residuals. Teuchos::LAPACK<int,double> lapack; std::vector<double> normR(numev); if (MyProblem->isHermitian()) { // Get storage Epetra_MultiVector Kevecs(*Map,numev); Teuchos::RCP<Epetra_MultiVector> Mevecs; Teuchos::SerialDenseMatrix<int,double> B(numev,numev); B.putScalar(0.0); for (int i=0; i<numev; i++) {B(i,i) = evals[i].realpart;} // Compute A*evecs OPT::Apply( *K, *evecs, Kevecs ); if (haveM) { Mevecs = Teuchos::rcp( new Epetra_MultiVector(*Map,numev) ); OPT::Apply( *M, *evecs, *Mevecs ); } else { Mevecs = evecs; } // Compute A*evecs - lambda*evecs and its norm MVT::MvTimesMatAddMv( -1.0, *Mevecs, B, 1.0, Kevecs ); MVT::MvNorm( Kevecs, normR ); // Scale the norms by the eigenvalue for (int i=0; i<numev; i++) { normR[i] /= Teuchos::ScalarTraits<double>::magnitude( evals[i].realpart ); } } else { // The problem is non-Hermitian. int i=0; std::vector<int> curind(1); std::vector<double> resnorm(1), tempnrm(1); Teuchos::RCP<MV> tempKevec, Mevecs; Teuchos::RCP<const MV> tempeveci, tempMevec; Epetra_MultiVector Kevecs(*Map,numev); // Compute K*evecs OPT::Apply( *K, *evecs, Kevecs ); if (haveM) { Mevecs = Teuchos::rcp( new Epetra_MultiVector(*Map,numev) ); OPT::Apply( *M, *evecs, *Mevecs ); } else { Mevecs = evecs; } Teuchos::SerialDenseMatrix<int,double> Breal(1,1), Bimag(1,1); while (i<numev) { if (index[i]==0) { // Get a view of the M*evecr curind[0] = i; tempMevec = MVT::CloneView( *Mevecs, curind ); // Get a copy of A*evecr tempKevec = MVT::CloneCopy( Kevecs, curind ); // Compute K*evecr - lambda*M*evecr Breal(0,0) = evals[i].realpart; MVT::MvTimesMatAddMv( -1.0, *tempMevec, Breal, 1.0, *tempKevec ); // Compute the norm of the residual and increment counter MVT::MvNorm( *tempKevec, resnorm ); normR[i] = resnorm[0]/Teuchos::ScalarTraits<double>::magnitude( evals[i].realpart ); i++; } else { // Get a view of the real part of M*evecr curind[0] = i; tempMevec = MVT::CloneView( *Mevecs, curind ); // Get a copy of K*evecr tempKevec = MVT::CloneCopy( Kevecs, curind ); // Get a view of the imaginary part of the eigenvector (eveci) curind[0] = i+1; tempeveci = MVT::CloneView( *Mevecs, curind ); // Set the eigenvalue into Breal and Bimag Breal(0,0) = evals[i].realpart; Bimag(0,0) = evals[i].imagpart; // Compute K*evecr - M*evecr*lambdar + M*eveci*lambdai MVT::MvTimesMatAddMv( -1.0, *tempMevec, Breal, 1.0, *tempKevec ); MVT::MvTimesMatAddMv( 1.0, *tempeveci, Bimag, 1.0, *tempKevec ); MVT::MvNorm( *tempKevec, tempnrm ); // Get a copy of K*eveci tempKevec = MVT::CloneCopy( Kevecs, curind ); // Compute K*eveci - M*eveci*lambdar - M*evecr*lambdai MVT::MvTimesMatAddMv( -1.0, *tempMevec, Bimag, 1.0, *tempKevec ); MVT::MvTimesMatAddMv( -1.0, *tempeveci, Breal, 1.0, *tempKevec ); MVT::MvNorm( *tempKevec, resnorm ); // Compute the norms and scale by magnitude of eigenvalue normR[i] = lapack.LAPY2( tempnrm[i], resnorm[i] ) / lapack.LAPY2( evals[i].realpart, evals[i].imagpart ); normR[i+1] = normR[i]; i=i+2; } } } // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { cout.setf(std::ios_base::right, std::ios_base::adjustfield); cout<<endl<< "Actual Residuals"<<endl; if (MyProblem->isHermitian()) { cout<< std::setw(16) << "Real Part" << std::setw(20) << "Direct Residual"<< endl; cout<<"-----------------------------------------------------------"<<endl; for (int i=0; i<numev; i++) { cout<< std::setw(16) << evals[i].realpart << std::setw(20) << normR[i] << endl; } cout<<"-----------------------------------------------------------"<<endl; } else { cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::setw(20) << "Direct Residual"<< endl; cout<<"-----------------------------------------------------------"<<endl; for (int i=0; i<numev; i++) { cout<< std::setw(16) << evals[i].realpart << std::setw(16) << evals[i].imagpart << std::setw(20) << normR[i] << endl; } cout<<"-----------------------------------------------------------"<<endl; } } } #ifdef EPETRA_MPI MPI_Finalize() ; #endif return 0; } // end BlockKrylovSchurEpetraExFile.cpp
int main(int argc, char *argv[]) { using std::cout; using std::endl; // bool haveM = true; #ifdef EPETRA_MPI // Initialize MPI MPI_Init(&argc,&argv); Epetra_MpiComm Comm( MPI_COMM_WORLD ); #else Epetra_SerialComm Comm; #endif int MyPID = Comm.MyPID(); bool verbose=false; bool isHermitian=false; std::string k_filename = "bfw782a.mtx"; std::string m_filename = "bfw782b.mtx"; std::string which = "LR"; Teuchos::CommandLineProcessor cmdp(false,true); cmdp.setOption("verbose","quiet",&verbose,"Print messages and results."); cmdp.setOption("sort",&which,"Targetted eigenvalues (SM,LM,SR,or LR)."); cmdp.setOption("K-filename",&k_filename,"Filename and path of the stiffness matrix."); cmdp.setOption("M-filename",&m_filename,"Filename and path of the mass matrix."); if (cmdp.parse(argc,argv) != Teuchos::CommandLineProcessor::PARSE_SUCCESSFUL) { #ifdef HAVE_MPI MPI_Finalize(); #endif return -1; } // //********************************************************************** //******************Set up the problem to be solved********************* //********************************************************************** // // *****Read in matrix from file****** // Teuchos::RCP<Epetra_Map> Map; Teuchos::RCP<Epetra_CrsMatrix> K, M; EpetraExt::readEpetraLinearSystem( k_filename, Comm, &K, &Map ); if (haveM) { EpetraExt::readEpetraLinearSystem( m_filename, Comm, &M, &Map ); } // // Build Preconditioner // Ifpack factory; std::string ifpack_type = "ILUT"; int overlap = 0; Teuchos::RCP<Ifpack_Preconditioner> ifpack_prec = Teuchos::rcp( factory.Create( ifpack_type, K.get(), overlap ) ); // // Set parameters and compute preconditioner // Teuchos::ParameterList ifpack_params; double droptol = 1e-2; double fill = 2.0; ifpack_params.set("fact: drop tolerance",droptol); ifpack_params.set("fact: ilut level-of-fill",fill); ifpack_prec->SetParameters(ifpack_params); ifpack_prec->Initialize(); ifpack_prec->Compute(); // // GeneralizedDavidson expects preconditioner to be applied with // "Apply" rather than "Apply_Inverse" // Teuchos::RCP<Epetra_Operator> prec = Teuchos::rcp( new Epetra_InvOperator(ifpack_prec.get()) ); // //************************************ // Start the block Davidson iteration //*********************************** // // Variables used for the Block Arnoldi Method // int nev = 5; int blockSize = 5; int maxDim = 40; int maxRestarts = 10; double tol = 1.0e-8; // Set verbosity level int verbosity = Anasazi::Errors + Anasazi::Warnings; if (verbose) { verbosity += Anasazi::FinalSummary + Anasazi::TimingDetails; } // // Create parameter list to pass into solver // Teuchos::ParameterList MyPL; MyPL.set( "Verbosity", verbosity ); MyPL.set( "Which", which ); MyPL.set( "Block Size", blockSize ); MyPL.set( "Maximum Subspace Dimension", maxDim ); MyPL.set( "Maximum Restarts", maxRestarts ); MyPL.set( "Convergence Tolerance", tol ); MyPL.set( "Initial Guess", "User" ); typedef Epetra_MultiVector MV; typedef Epetra_Operator OP; typedef Anasazi::MultiVecTraits<double, MV> MVT; typedef Anasazi::OperatorTraits<double, MV, OP> OPT; // // Create the eigenproblem to be solved. // Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(*Map, blockSize) ); ivec->Random(); Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > MyProblem; if (haveM) { MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>() ); MyProblem->setA(K); MyProblem->setM(M); MyProblem->setPrec(prec); MyProblem->setInitVec(ivec); } else { MyProblem = Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>() ); MyProblem->setA(K); MyProblem->setPrec(prec); MyProblem->setInitVec(ivec); } // Inform the eigenproblem that the (K,M) is Hermitian MyProblem->setHermitian( isHermitian ); // Set the number of eigenvalues requested MyProblem->setNEV( nev ); // Inform the eigenproblem that you are finished passing it information bool boolret = MyProblem->setProblem(); if (boolret != true) { if (verbose && MyPID == 0) { cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << endl; } #ifdef HAVE_MPI MPI_Finalize() ; #endif return -1; } // Initialize the Block Arnoldi solver Anasazi::GeneralizedDavidsonSolMgr<double, MV, OP> MySolverMgr(MyProblem, MyPL); // Solve the problem to the specified tolerances or length Anasazi::ReturnType returnCode = MySolverMgr.solve(); if (returnCode != Anasazi::Converged && MyPID==0 && verbose) { cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << endl; } // Get the eigenvalues and eigenvectors from the eigenproblem Anasazi::Eigensolution<double,MV> sol = MyProblem->getSolution(); std::vector<Anasazi::Value<double> > evals = sol.Evals; Teuchos::RCP<MV> evecs = sol.Evecs; std::vector<int> index = sol.index; int numev = sol.numVecs; if (numev > 0) { // Compute residuals. Teuchos::LAPACK<int,double> lapack; std::vector<double> normR(numev); // The problem is non-Hermitian. int i=0; std::vector<int> curind(1); std::vector<double> resnorm(1), tempnrm(1); Teuchos::RCP<MV> tempKevec, Mevecs; Teuchos::RCP<const MV> tempeveci, tempMevec; Epetra_MultiVector Kevecs(*Map,numev); // Compute K*evecs OPT::Apply( *K, *evecs, Kevecs ); if (haveM) { Mevecs = Teuchos::rcp( new Epetra_MultiVector(*Map,numev) ); OPT::Apply( *M, *evecs, *Mevecs ); } else { Mevecs = evecs; } Teuchos::SerialDenseMatrix<int,double> Breal(1,1), Bimag(1,1); while (i<numev) { if (index[i]==0) { // Get a view of the M*evecr curind[0] = i; tempMevec = MVT::CloneView( *Mevecs, curind ); // Get a copy of A*evecr tempKevec = MVT::CloneCopy( Kevecs, curind ); // Compute K*evecr - lambda*M*evecr Breal(0,0) = evals[i].realpart; MVT::MvTimesMatAddMv( -1.0, *tempMevec, Breal, 1.0, *tempKevec ); // Compute the norm of the residual and increment counter MVT::MvNorm( *tempKevec, resnorm ); normR[i] = resnorm[0]; i++; } else { // Get a view of the real part of M*evecr curind[0] = i; tempMevec = MVT::CloneView( *Mevecs, curind ); // Get a copy of K*evecr tempKevec = MVT::CloneCopy( Kevecs, curind ); // Get a view of the imaginary part of the eigenvector (eveci) curind[0] = i+1; tempeveci = MVT::CloneView( *Mevecs, curind ); // Set the eigenvalue into Breal and Bimag Breal(0,0) = evals[i].realpart; Bimag(0,0) = evals[i].imagpart; // Compute K*evecr - M*evecr*lambdar + M*eveci*lambdai MVT::MvTimesMatAddMv( -1.0, *tempMevec, Breal, 1.0, *tempKevec ); MVT::MvTimesMatAddMv( 1.0, *tempeveci, Bimag, 1.0, *tempKevec ); MVT::MvNorm( *tempKevec, tempnrm ); // Get a copy of K*eveci tempKevec = MVT::CloneCopy( Kevecs, curind ); // Compute K*eveci - M*eveci*lambdar - M*evecr*lambdai MVT::MvTimesMatAddMv( -1.0, *tempMevec, Bimag, 1.0, *tempKevec ); MVT::MvTimesMatAddMv( -1.0, *tempeveci, Breal, 1.0, *tempKevec ); MVT::MvNorm( *tempKevec, resnorm ); // Compute the norms and scale by magnitude of eigenvalue normR[i] = lapack.LAPY2( tempnrm[0], resnorm[0] ); normR[i+1] = normR[i]; i=i+2; } } // Output computed eigenvalues and their direct residuals if (verbose && MyPID==0) { cout.setf(std::ios_base::right, std::ios_base::adjustfield); cout<<endl<< "Actual Residuals"<<endl; cout<< std::setw(16) << "Real Part" << std::setw(16) << "Imag Part" << std::setw(20) << "Direct Residual"<< endl; cout<<"-----------------------------------------------------------"<<endl; for (int j=0; j<numev; j++) { cout<< std::setw(16) << evals[j].realpart << std::setw(16) << evals[j].imagpart << std::setw(20) << normR[j] << endl; } cout<<"-----------------------------------------------------------"<<endl; } } #ifdef EPETRA_MPI MPI_Finalize() ; #endif return 0; } // end BlockKrylovSchurEpetraExFile.cpp