00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <SymBandEigenSolver.h>
00033 #include <f2c.h>
00034 #include <math.h>
00035 #include <stdio.h>
00036 #include <AnalysisModel.h>
00037 #include <DOF_GrpIter.h>
00038 #include <DOF_Group.h>
00039 #include <FE_EleIter.h>
00040 #include <FE_Element.h>
00041 #include <Integrator.h>
00042
00043 SymBandEigenSolver::SymBandEigenSolver()
00044 :EigenSolver(EigenSOLVER_TAGS_SymBandEigenSolver),
00045 theSOE(0), numModes(0), eigenvalue(0), eigenvector(0), eigenV(0)
00046 {
00047
00048 }
00049
00050 SymBandEigenSolver::~SymBandEigenSolver()
00051 {
00052 if (eigenvalue != 0)
00053 delete [] eigenvalue;
00054 if (eigenvector != 0)
00055 delete [] eigenvector;
00056 if (eigenV != 0)
00057 delete eigenV;
00058 }
00059
00060 #ifdef _WIN32
00061
00062 extern "C" int DSBEVX(char *jobz, char *range, char *uplo, int *n, int *kd,
00063 double *ab, int *ldab, double *q, int *ldq,
00064 double *vl, double *vu, int *il, int *iu, double *abstol,
00065 int *m, double *w, double *z, int *ldz,
00066 double *work, int *iwork, int *ifail, int *info);
00067
00068 #else
00069
00070 extern "C" int dsbevx_(char *jobz, char *range, char *uplo, int *n, int *kd,
00071 double *ab, int *ldab, double *q, int *ldq,
00072 double *vl, double *vu, int *il, int *iu, double *abstol,
00073 int *m, double *w, double *z, int *ldz,
00074 double *work, int *iwork, int *ifail, int *info);
00075
00076 #endif
00077
00078 int
00079 SymBandEigenSolver::solve(int nModes)
00080 {
00081 if (theSOE == 0) {
00082 opserr << "SymBandEigenSolver::solve() -- no EigenSOE has been set yet\n";
00083 return -1;
00084 }
00085
00086
00087 numModes = nModes;
00088
00089
00090 int n = theSOE->size;
00091
00092
00093 if (numModes < 1) {
00094 numModes = 0;
00095 return 0;
00096 }
00097
00098
00099 if (numModes > n)
00100 numModes = n;
00101
00102
00103 if (eigenvalue != 0)
00104 delete [] eigenvalue;
00105 eigenvalue = new double [n];
00106
00107
00108 double *work = new double [7*n];
00109
00110
00111 int *iwork = new int [5*n];
00112
00113
00114 int ldz = n;
00115
00116
00117 if (eigenvector != 0)
00118 delete [] eigenvector;
00119 eigenvector = new double [ldz*numModes];
00120
00121
00122 int kd = theSOE->numSuperD;
00123
00124
00125 double *ab = theSOE->A;
00126
00127
00128 int ldab = kd + 1;
00129
00130
00131 int ldq = n;
00132
00133
00134
00135 double *q = new double [ldq*n];
00136
00137
00138 int il = 1;
00139 int iu = numModes;
00140
00141
00142 char *jobz = "V";
00143
00144
00145 char *range = "I";
00146
00147
00148 char *uplo = "U";
00149
00150
00151 int *ifail = new int [n];
00152 int info = 0;
00153
00154
00155 int m = 0;
00156
00157
00158 double vl = 0.0;
00159 double vu = 1.0;
00160
00161
00162 double abstol = -1.0;
00163
00164
00165
00166
00167 double *M = theSOE->M;
00168 double *A = theSOE->A;
00169 int numSuperD = theSOE->numSuperD;
00170 int size = n;
00171 if (M != 0) {
00172 int i,j;
00173 bool singular = false;
00174
00175 for (int k=0; k<size; k++) {
00176 if (M[k] == 0.0) {
00177 singular = true;
00178
00179 opserr << "SymBandEigenSolver::solve() - M matrix singular\n";
00180 return -1;
00181 } else {
00182 M[k] = 1.0/sqrt(M[k]);
00183 }
00184 }
00185
00186
00187
00188 for (i=0; i<size; i++) {
00189 double *AijPtr = A +(i+1)*(numSuperD+1) - 1;
00190 int minColRow = i - numSuperD;
00191 if (minColRow < 0) minColRow = 0;
00192 for (j=i; j>=minColRow; j--) {
00193 *AijPtr *= M[j]*M[i];
00194 AijPtr--;
00195 }
00196 }
00197 }
00198
00199
00200 #ifdef _WIN32
00201 unsigned int sizeC = 1;
00202 DSBEVX(jobz, range, uplo, &n, &kd, ab, &ldab,
00203 q, &ldq, &vl, &vu, &il, &iu, &abstol, &m,
00204 eigenvalue, eigenvector, &ldz, work, iwork, ifail, &info);
00205 #else
00206 dsbevx_(jobz, range, uplo, &n, &kd, ab, &ldab,
00207 q, &ldq, &vl, &vu, &il, &iu, &abstol, &m,
00208 eigenvalue, eigenvector, &ldz, work, iwork, ifail, &info);
00209 #endif
00210
00211 delete [] q;
00212 delete [] work;
00213 delete [] iwork;
00214 delete [] ifail;
00215
00216 if (info < 0) {
00217 opserr << "SymBandEigenSolver::solve() -- invalid argument number " << -info << " passed to LAPACK dsbevx\n";
00218 return info;
00219 }
00220
00221 if (info > 0) {
00222 opserr << "SymBandEigenSolver::solve() -- LAPACK dsbevx returned error code " << info << endln;
00223 return -info;
00224 }
00225
00226 if (m < numModes) {
00227 opserr << "SymBandEigenSolver::solve() -- LAPACK dsbevx only computed " << m << " eigenvalues, " <<
00228 numModes << "were requested\n";
00229
00230 numModes = m;
00231 }
00232
00233 theSOE->factored = true;
00234
00235
00236
00237
00238
00239 M = theSOE->M;
00240 if (M != 0) {
00241
00242 for (int j=0; j<numModes; j++) {
00243 double *eigVectJptr = &eigenvector[j*ldz];
00244 double *MPtr = M;
00245 for (int i=0; i<size; i++)
00246 *eigVectJptr++ *= *MPtr++;
00247 }
00248 }
00249
00250 return 0;
00251 }
00252
00253 int
00254 SymBandEigenSolver::setEigenSOE(SymBandEigenSOE &theBandSOE)
00255 {
00256 theSOE = &theBandSOE;
00257
00258 return 0;
00259 }
00260
00261 const Vector &
00262 SymBandEigenSolver::getEigenvector(int mode)
00263 {
00264 if (mode < 1 || mode > numModes) {
00265 opserr << "SymBandEigenSolver::getEigenVector() -- mode " << mode << " is out of range (1 - "
00266 << numModes << ")\n";
00267
00268 eigenV->Zero();
00269 return *eigenV;
00270 }
00271
00272 int size = theSOE->size;
00273
00274 int index = (mode - 1) * size;
00275
00276 Vector &vec = *eigenV;
00277 if (eigenvector != 0) {
00278 for (int i = 0; i < size; i++) {
00279 vec(i) = eigenvector[index++];
00280 }
00281 }
00282 else {
00283 opserr << "SymBandEigenSolver::getEigenVector() -- eigenvectors not yet computed\n";
00284 eigenV->Zero();
00285 }
00286
00287 return *eigenV;
00288 }
00289
00290 double
00291 SymBandEigenSolver::getEigenvalue(int mode)
00292 {
00293 if (mode < 1 || mode > numModes) {
00294 opserr << "SymBandEigenSolver::getEigenvalue() -- mode " << mode << " is out of range (1 - "
00295 << numModes << ")\n";
00296
00297 return 0.0;
00298 }
00299
00300 if (eigenvalue != 0)
00301 return eigenvalue[mode-1];
00302 else {
00303 opserr << "SymBandEigenSolver::getEigenvalue() -- eigenvalues not yet computed\n";
00304 return 0.0;
00305 }
00306 }
00307
00308 int
00309 SymBandEigenSolver::setSize()
00310 {
00311 int size = theSOE->size;
00312
00313 if (eigenV == 0 || eigenV->Size() != size) {
00314 if (eigenV != 0)
00315 delete eigenV;
00316
00317 eigenV = new Vector(size);
00318 if (eigenV == 0 || eigenV->Size() != size) {
00319 opserr << "SymBandEigenSolver::ssetSize() -- ran out of memory for eigenvector of size " << size << endln;
00320 return -2;
00321 }
00322 }
00323
00324 return 0;
00325 }
00326
00327 int
00328 SymBandEigenSolver::sendSelf(int commitTag, Channel &theChannel)
00329 {
00330 return 0;
00331 }
00332
00333 int
00334 SymBandEigenSolver::recvSelf(int commitTag, Channel &theChannel,
00335 FEM_ObjectBroker &theBroker)
00336 {
00337 return 0;
00338 }