int XC::SymBandEigenSolver::solve(int nModes) { if(!theSOE) { std::cerr << "SymBandEigenSolver::solve() -- no XC::EigenSOE has been set yet\n"; return -1; } // Set number of modes numModes= nModes; // Number of equations int n= theSOE->size; // Check for quick return if(numModes < 1) { numModes= 0; return 0; } // Simple check if(numModes > n) numModes= n; // Allocate storage for eigenvalues eigenvalue.resize(n); // Real work array (see LAPACK dsbevx subroutine documentation) work.resize(7*n); // Integer work array (see LAPACK dsbevx subroutine documentation) std::vector<int> iwork(5*n); // Leading dimension of eigenvectors int ldz = n; // Allocate storage for eigenvectors eigenvector.resize(ldz*numModes); // Number of superdiagonals int kd= theSOE->numSuperD; // Matrix data double *ab= theSOE->A.getDataPtr(); // Leading dimension of the matrix int ldab= kd + 1; // Leading dimension of q int ldq= n; // Orthogonal matrix used in reduction to tridiagonal form // (see LAPACK dsbevx subroutine documentation) std::vector<double> q(ldq*n); // Index ranges [1,numModes] of eigenpairs to compute int il = 1; int iu = numModes; // Compute eigenvalues and eigenvectors char jobz[] = "V"; // Selected eigenpairs are based on index range [il,iu] char range[] = "I"; // Upper triagle of matrix is stored char uplo[] = "U"; // Return value std::vector<int> ifail(n); int info= 0; // Number of eigenvalues returned int m= 0; // Not used double vl = 0.0; double vu = 1.0; // Not used ... I think! double abstol = -1.0; // if Mass matrix we make modifications to A: // A -> M^(-1/2) A M^(-1/2) double *M= theSOE->M.getDataPtr(); double *A= theSOE->A.getDataPtr(); int numSuperD = theSOE->numSuperD; int size = n; if(M) //Its seems that the M matrix must be DIAGONAL. { int i,j; bool singular = false; // form M^(-1/2) and check for singular mass matrix for(int k=0; k<size; k++) { if(M[k] == 0.0) { singular = true; // alternative is to set as a small no ~ 1e-10 times smallest m(i,i) != 0.0 std::cerr << "SymBandEigenSolver::solve() - M matrix singular\n"; return -1; } else { M[k] = 1.0/sqrt(M[k]); } } // make modifications to A // Aij -> Mi Aij Mj (based on new_ M) for(i=0; i<size; i++) { double *AijPtr = A +(i+1)*(numSuperD+1) - 1; int minColRow = i - numSuperD; if(minColRow < 0) minColRow = 0; for(j=i; j>=minColRow; j--) { *AijPtr *= M[j]*M[i]; AijPtr--; } } } // Calls the LAPACK routine that computes the eigenvalues and eigenvectors // of the matrix A previously transforme. dsbevx_(jobz, range, uplo, &n, &kd, ab, &ldab, &q[0], &ldq, &vl, &vu, &il, &iu, &abstol, &m, eigenvalue.getDataPtr(), eigenvector.getDataPtr(), &ldz, work.getDataPtr(), &iwork[0], &ifail[0], &info); if(info < 0) { std::cerr << "SymBandEigenSolver::solve() -- invalid argument number " << -info << " passed to LAPACK dsbevx\n"; return info; } if(info > 0) { std::cerr << "SymBandEigenSolver::solve() -- LAPACK dsbevx returned error code " << info << std::endl; return -info; } if(m < numModes) { std::cerr << "SymBandEigenSolver::solve() -- LAPACK dsbevx only computed " << m << " eigenvalues, " << numModes << "were requested\n"; numModes = m; } theSOE->factored = true; // make modifications to the eigenvectors // Eij -> Mi Eij (based on new_ M) M= theSOE->M.getDataPtr(); if(M) { for(int j=0; j<numModes; j++) { double *eigVectJptr = &eigenvector[j*ldz]; double *MPtr = M; for(int i=0; i<size; i++) *eigVectJptr++ *= *MPtr++; } } return 0; }
int SymBandEigenSolver::solve(int nModes, bool generalized, bool findSmallest) { if (generalized == true) { opserr << "SymBandEigenSolver::solve() - only does standard problem\n"; return -1; } if (theSOE == 0) { opserr << "SymBandEigenSolver::solve() -- no EigenSOE has been set yet\n"; return -1; } // Set number of modes numModes = nModes; // Number of equations int n = theSOE->size; // Check for quick return if (numModes < 1) { numModes = 0; return 0; } // Simple check if (numModes > n) numModes = n; // Allocate storage for eigenvalues if (eigenvalue != 0) delete [] eigenvalue; eigenvalue = new double [n]; // Real work array (see LAPACK dsbevx subroutine documentation) double *work = new double [7*n]; // Integer work array (see LAPACK dsbevx subroutine documentation) int *iwork = new int [5*n]; // Leading dimension of eigenvectors int ldz = n; // Allocate storage for eigenvectors if (eigenvector != 0) delete [] eigenvector; eigenvector = new double [ldz*numModes]; // Number of superdiagonals int kd = theSOE->numSuperD; // Matrix data double *ab = theSOE->A; // Leading dimension of the matrix int ldab = kd + 1; // Leading dimension of q int ldq = n; // Orthogonal matrix used in reduction to tridiagonal form // (see LAPACK dsbevx subroutine documentation) double *q = new double [ldq*n]; // Index ranges [1,numModes] of eigenpairs to compute int il = 1; int iu = numModes; // Compute eigenvalues and eigenvectors char *jobz = "V"; // Selected eigenpairs are based on index range [il,iu] char *range = "I"; // Upper triagle of matrix is stored char *uplo = "U"; // Return value int *ifail = new int [n]; int info = 0; // Number of eigenvalues returned int m = 0; // Not used double vl = 0.0; double vu = 1.0; // Not used ... I think! double abstol = -1.0; // if Mass matrix we make modifications to A: // A -> M^(-1/2) A M^(-1/2) double *M = theSOE->M; double *A = theSOE->A; int numSuperD = theSOE->numSuperD; int size = n; if (M != 0) { int i,j; bool singular = false; // form M^(-1/2) and check for singular mass matrix for (int k=0; k<size; k++) { if (M[k] == 0.0) { singular = true; // alternative is to set as a small no ~ 1e-10 times smallest m(i,i) != 0.0 opserr << "SymBandEigenSolver::solve() - M matrix singular\n"; return -1; } else { M[k] = 1.0/sqrt(M[k]); } } // make modifications to A // Aij -> Mi Aij Mj (based on new M) for (i=0; i<size; i++) { double *AijPtr = A +(i+1)*(numSuperD+1) - 1; int minColRow = i - numSuperD; if (minColRow < 0) minColRow = 0; for (j=i; j>=minColRow; j--) { *AijPtr *= M[j]*M[i]; AijPtr--; } } } // Call the LAPACK eigenvalue subroutine #ifdef _WIN32 unsigned int sizeC = 1; DSBEVX(jobz, range, uplo, &n, &kd, ab, &ldab, q, &ldq, &vl, &vu, &il, &iu, &abstol, &m, eigenvalue, eigenvector, &ldz, work, iwork, ifail, &info); #else dsbevx_(jobz, range, uplo, &n, &kd, ab, &ldab, q, &ldq, &vl, &vu, &il, &iu, &abstol, &m, eigenvalue, eigenvector, &ldz, work, iwork, ifail, &info); #endif delete [] q; delete [] work; delete [] iwork; delete [] ifail; if (info < 0) { opserr << "SymBandEigenSolver::solve() -- invalid argument number " << -info << " passed to LAPACK dsbevx\n"; return info; } if (info > 0) { opserr << "SymBandEigenSolver::solve() -- LAPACK dsbevx returned error code " << info << endln; return -info; } if (m < numModes) { opserr << "SymBandEigenSolver::solve() -- LAPACK dsbevx only computed " << m << " eigenvalues, " << numModes << "were requested\n"; numModes = m; } theSOE->factored = true; // make modifications to the eigenvectors // Eij -> Mi Eij (based on new M) M = theSOE->M; if (M != 0) { for (int j=0; j<numModes; j++) { double *eigVectJptr = &eigenvector[j*ldz]; double *MPtr = M; for (int i=0; i<size; i++) *eigVectJptr++ *= *MPtr++; } } return 0; }
int MatrixOperations::performEigenAnalysis(int pBeginMod, int pEndMod) { beginMod=pBeginMod; endMod = pEndMod; Matrix * A = theMatrix; // opserr<< "hessian:"<< * theMatrix<<endln; if (A ==0) {opserr<<"error, Hessian does not exist in MatrixOperator::performEigenAnalysis !"<<endln; exit(-1);} // Number of equations int n = A->noRows(); if (n != A->noCols()) { opserr<<"MatrixOperations::performEigenAnalysis wrong. m!=n"<<endln; exit(-1); } numModes = endMod - beginMod +1; //Q // Check for quick return if (numModes < 1) { numModes = 0; return 0; } // Simple check if (numModes > n) numModes = n; // Allocate storage for eigenvalues if (eigenvalue != 0) delete [] eigenvalue; eigenvalue = new double [n]; // Real work array (see LAPACK dsbevx subroutine documentation) double *work = new double [7*n]; // Integer work array (see LAPACK dsbevx subroutine documentation) int *iwork = new int [5*n]; // Leading dimension of eigenvectors int ldz = n; setSizeOfEigenVector(ldz); // alloc memory here. // Allocate storage for eigenvectors if (eigenvector != 0) delete [] eigenvector; eigenvector = new double [ldz*numModes]; // Number of superdiagonals int kd = n-1; // Matrix data //double *ab = theSOE->A; // double *ab = new double [n*n]; int i; for (i=0; i<n*n; i++) ab[i]=0.0; for (i=0; i<n; i++) for (int j=i; j<n; j++) ab[kd+i-j+n*j]= (*A)(i,j); // opserr<<"Hessian:"<<(*A)<<endln; //opserr<<"ab:"<<endln; /* for (i=0; i<n; i++) for (int j=0; j<n; j++) opserr<< ab[n*i+j]<<endln;*/ // Leading dimension of the matrix int ldab = kd + 1; // Leading dimension of q int ldq = n; // Orthogonal matrix used in reduction to tridiagonal form // (see LAPACK dsbevx subroutine documentation) double *q = new double [ldq*n]; // Index ranges [1,numModes] of eigenpairs to compute int il = beginMod; int iu = endMod; // Compute eigenvalues and eigenvectors char jobz[3] = "V"; // Selected eigenpairs are based on index range [il,iu] char range[3] = "I"; // Upper triagle of matrix is stored char uplo[3] = "U"; // Return value int *ifail = new int [n]; int info = 0; // Number of eigenvalues returned int m = 0; // Not used double vl = 0.0; double vu = 1.0; // Not used double abstol = -1.0; // Call the LAPACK eigenvalue subroutine #ifdef _WIN32 unsigned int sizeC = 1; DSBEVX(jobz, range, uplo, &n, &kd, ab, &ldab, q, &ldq, &vl, &vu, &il, &iu, &abstol, &m, eigenvalue, eigenvector, &ldz, work, iwork, ifail, &info); #else dsbevx_(jobz, range, uplo, &n, &kd, ab, &ldab, q, &ldq, &vl, &vu, &il, &iu, &abstol, &m, eigenvalue, eigenvector, &ldz, work, iwork, ifail, &info); #endif delete [] q; delete [] work; delete [] iwork; delete [] ifail; if (info < 0) { opserr << "Hessian::performEigenAnalysis() -- invalid argument number " << -info << " passed to LAPACK dsbevx\n"; return info; } if (info > 0) { opserr << "Hessian::performEigenAnalysis() -- LAPACK dsbevx returned error code " << info << endln; return -info; } if (m < numModes) { opserr << "Hessian::performEigenAnalysis() -- LAPACK dsbevx only computed " << m << " eigenvalues, " << numModes << "were requested\n"; numModes = m; } return 0; }