Ejemplo n.º 1
0
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;
  }
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
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;

}