//============================================================================= void Epetra_LAPACK::GGEV(const char JOBVL, const char JOBVR, const int N, double* A, const int LDA, double* B, const int LDB, double* ALPHAR, double* ALPHAI, double* BETA, double* VL, const int LDVL, double* VR, const int LDVR, double* WORK, const int LWORK, int* INFO) const{ #ifdef EPETRA_LAPACK3 DGGEV_F77(CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), &N, A, &LDA, B, &LDB, ALPHAR, ALPHAI, BETA, VL, &LDVL, VR, &LDVR, WORK, &LWORK, INFO); #else Epetra_Object obj; obj.ReportError("GGEV requires LAPACK Version 3. Compile Epetra with -DEPETRA_LAPACK3 and link with LAPACK 3 library", -1); #endif }
NOX::Abstract::Group::ReturnType LOCA::Eigensolver::DGGEVStrategy::computeEigenvalues( NOX::Abstract::Group& group, Teuchos::RCP< std::vector<double> >& evals_r, Teuchos::RCP< std::vector<double> >& evals_i, Teuchos::RCP< NOX::Abstract::MultiVector >& evecs_r, Teuchos::RCP< NOX::Abstract::MultiVector >& evecs_i) { // Get LAPACK group LOCA::LAPACK::Group* grp = dynamic_cast<LOCA::LAPACK::Group*>(&group); bool hasMassMatrix = true; if (globalData->locaUtils->isPrintType(NOX::Utils::StepperIteration)) { globalData->locaUtils->out() << std::endl << globalData->locaUtils->fill(64,'=') << std::endl << "LAPACK "; if (hasMassMatrix) globalData->locaUtils->out() << "DGGEV "; else globalData->locaUtils->out() << "DGEEV "; globalData->locaUtils->out() << "Eigensolver starting." << std::endl << std::endl;; } // Make sure Jacobian & mass matrices are fresh grp->computeJacobian(); if (hasMassMatrix) grp->computeShiftedMatrix(0.0, 1.0); // Get data out of group NOX::LAPACK::Matrix<double>& jacobianMatrix = grp->getJacobianMatrix(); NOX::LAPACK::Matrix<double>& massMatrix = grp->getShiftedMatrix(); // Size of matrix int n = jacobianMatrix.numRows(); int lda = jacobianMatrix.numRows(); int ldb = massMatrix.numRows(); // Space to hold right eigenvectors double *vr = new double[n*n]; // Space to hold real and imaginary eigenvalues double *alphar = new double[n]; double *alphai = new double[n]; double *beta = new double[n]; // Size of work array, set to -1 to do a workspace query int lwork = -1; // Initial work "array" double work0; // Actual work array double *work; // Return code int info; // Copy Jacobian matrix since lapack routines overwrite it NOX::LAPACK::Matrix<double> J(jacobianMatrix); NOX::LAPACK::Matrix<double> M; // First do a workspace query if (hasMassMatrix) { // Copy mass matrix since lapack routines overwrite it M = massMatrix; DGGEV_F77("N", "V", &n, &J(0,0), &lda, &M(0,0), &ldb, alphar, alphai, beta, vr, &n, vr, &n, &work0, &lwork, &info); } else { DGEEV_F77("N", "V", &n, &J(0,0), &lda, alphar, alphai, vr, &n, vr, &n, &work0, &lwork, &info); } // Allocate work array lwork = (int) work0; work = new double[lwork]; // Calculate eigenvalues, eigenvectors if (hasMassMatrix) { DGGEV_F77("N", "V", &n, &J(0,0), &lda, &M(0,0), &ldb, alphar, alphai, beta, vr, &n, vr, &n, work, &lwork, &info); } else { DGEEV_F77("N", "V", &n, &J(0,0), &lda, alphar, alphai, vr, &n, vr, &n, work, &lwork, &info); } // Check for success if (info != 0) return NOX::Abstract::Group::Failed; // Compute all of the eigenvalues and eigenvectors before sorting std::vector<double> evals_r_tmp(n); std::vector<double> evals_i_tmp(n); Teuchos::RCP<NOX::Abstract::MultiVector> evecs_r_tmp = group.getX().createMultiVector(n, NOX::ShapeCopy); Teuchos::RCP<NOX::Abstract::MultiVector>evecs_i_tmp = group.getX().createMultiVector(n, NOX::ShapeCopy); NOX::LAPACK::Vector* tmpr; NOX::LAPACK::Vector* tmpi; double rnext; double inext; bool isComplexEval = false; bool isPrevComplexEval = false; for (int j=0; j<n; j++) { // Compute eigenvalues if (hasMassMatrix) { evals_r_tmp[j] = alphar[j]/beta[j]; evals_i_tmp[j] = alphai[j]/beta[j]; } else { evals_r_tmp[j] = alphar[j]; evals_i_tmp[j] = alphai[j]; } // Compute next eigenvalue if (!isPrevComplexEval && j < n-1) { if (hasMassMatrix) { rnext = alphar[j+1]/beta[j+1]; inext = alphai[j+1]/beta[j+1]; } else { rnext = alphar[j+1]; inext = alphai[j+1]; } // Determine if this eigenvalue is a complex conjugate pair if (fabs(evals_r_tmp[j] - rnext) < 1.0e-14*fabs(1.0+evals_r_tmp[j]) && fabs(evals_i_tmp[j] + inext) < 1.0e-14*fabs(1.0+evals_i_tmp[j])) isComplexEval = true; else isComplexEval = false; } else if (!isPrevComplexEval && j == n-1) isComplexEval = false; tmpr = dynamic_cast<NOX::LAPACK::Vector*>(&((*evecs_r_tmp)[j])); tmpi = dynamic_cast<NOX::LAPACK::Vector*>(&((*evecs_i_tmp)[j])); if (isComplexEval) for (int i=0; i<n; i++) { (*tmpr)(i) = vr[i+j*n]; (*tmpi)(i) = vr[i+(j+1)*n]; } else if (isPrevComplexEval) for (int i=0; i<n; i++) { (*tmpr)(i) = vr[i+(j-1)*n]; (*tmpi)(i) = -vr[i+j*n]; } else for (int i=0; i<n; i++) { (*tmpr)(i) = vr[i+j*n]; (*tmpi)(i) = 0.0;; } if (isPrevComplexEval) { isPrevComplexEval = false; isComplexEval = false; } if (isComplexEval) { isPrevComplexEval = true; isComplexEval = false; } } // Instantiate a sorting strategy Teuchos::RCP<LOCA::EigenvalueSort::AbstractStrategy> evalSort = globalData->locaFactory->createEigenvalueSortStrategy(topParams, eigenParams); // Create permutation array std::vector<int> perm(n); // Sort eigenvalues evalSort->sort(n, &evals_r_tmp[0], &evals_i_tmp[0], &perm); // Get first nev entries of perm std::vector<int> perm_short(perm.begin(), perm.begin()+nev); // Get sorted eigenvalues and eigenvectors evals_r = Teuchos::rcp(new std::vector<double>(evals_r_tmp.begin(), evals_r_tmp.begin()+nev)); evals_i = Teuchos::rcp(new std::vector<double>(evals_i_tmp.begin(), evals_i_tmp.begin()+nev)); evecs_r = evecs_r_tmp->subCopy(perm_short); evecs_i = evecs_i_tmp->subCopy(perm_short); // Print out eigenvalues if (globalData->locaUtils->isPrintType(NOX::Utils::StepperIteration)) { for (int i=0; i<nev; i++) globalData->locaUtils->out() << "Eigenvalue " << i << " : " << globalData->locaUtils->sciformat((*evals_r)[i]) << " " << globalData->locaUtils->sciformat((*evals_i)[i]) << " i" << std::endl; } if (globalData->locaUtils->isPrintType(NOX::Utils::StepperIteration)) globalData->locaUtils->out() << "\nLAPACK Eigensolver finished.\n" << globalData->locaUtils->fill(64,'=') << "\n" << std::endl; delete [] alphar; delete [] alphai; delete [] beta; delete [] vr; delete [] work; return NOX::Abstract::Group::Ok; }