00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "SymArpackSOE.h"
00016 #include "SymArpackSolver.h"
00017 #include <f2c.h>
00018 #include <math.h>
00019 #include <Channel.h>
00020 #include <FEM_ObjectBroker.h>
00021 #include <AnalysisModel.h>
00022 #include <DOF_GrpIter.h>
00023 #include <DOF_Group.h>
00024 #include <FE_EleIter.h>
00025 #include <FE_Element.h>
00026 #include <Integrator.h>
00027
00028 extern "C" {
00029 #include <FeStructs.h>
00030 #include <globalVars.h>
00031 #include <tim.h>
00032 }
00033
00034 #ifdef _WIN32
00035 extern "C" int _stdcall DSAUPD(int *ido, char* bmat, unsigned int *,
00036 int *n, char *which, unsigned int *,
00037 int *nev,
00038 double *tol, double *resid, int *ncv, double *v,
00039 int *ldv,
00040 int *iparam, int *ipntr, double *workd, double *workl,
00041 int *lworkl, int *info);
00042
00043 extern "C" int _stdcall DSEUPD(bool *rvec, char *howmny, unsigned int *,
00044 logical *select, double *d, double *z,
00045 int *ldz, double *sigma, char *bmat, unsigned int *,
00046 int *n, char *which, unsigned int *,
00047 int *nev, double *tol, double *resid, int *ncv,
00048 double *v,
00049 int *ldv, int *iparam, int *ipntr, double *workd,
00050 double *workl, int *lworkl, int *info);
00051
00052 #else
00053
00054 extern "C" int dsaupd_(int *ido, char* bmat, int *n, char *which, int *nev,
00055 double *tol, double *resid, int *ncv, double *v, int *ldv,
00056 int *iparam, int *ipntr, double *workd, double *workl,
00057 int *lworkl, int *info);
00058
00059 extern "C" int dseupd_(bool *rvec, char *howmny, logical *select, double *d, double *z,
00060 int *ldz, double *sigma, char *bmat, int *n, char *which,
00061 int *nev, double *tol, double *resid, int *ncv, double *v,
00062 int *ldv, int *iparam, int *ipntr, double *workd,
00063 double *workl, int *lworkl, int *info);
00064
00065 #endif
00066
00067 SymArpackSolver::SymArpackSolver(int numE)
00068 :EigenSolver(EigenSOLVER_TAGS_SymArpackSolver),
00069 theSOE(0), factored(false), theNev(numE), eigenV(0)
00070 {
00071
00072 }
00073
00074
00075 SymArpackSolver::~SymArpackSolver()
00076 {
00077 if (value != 0)
00078 delete [] value;
00079
00080 if (vector !=0)
00081 delete [] vector;
00082 }
00083
00084
00085 extern "C" int pfsfct(int neqns, double *diag, double **penv, int nblks, int *xblk,
00086 OFFDBLK **begblk, OFFDBLK *first, int *rowblks);
00087
00088 extern "C" void pfsslv(int neqns, double *diag, double **penv, int nblks,
00089 int *xblk, double *rhs, OFFDBLK **begblk);
00090
00091
00092
00093 int
00094 SymArpackSolver::solve(void)
00095 {
00096 if (theSOE == 0) {
00097 cerr << "WARNING SymArpackSolver::solve(void)- ";
00098 cerr << " No EigenSOE object has been set\n";
00099 return -1;
00100 }
00101
00102 int nblks = theSOE->nblks;
00103 int *xblk = theSOE->xblk;
00104
00105 double *diag = theSOE->diag;
00106 double **penv = theSOE->penv;
00107 int *rowblks = theSOE->rowblks;
00108 OFFDBLK **begblk = theSOE->begblk;
00109 OFFDBLK *first = theSOE->first;
00110
00111 int n = theSOE->size;
00112
00113
00114 if (n == 0)
00115 return 0;
00116
00117 timer (FACTOR);
00118 if (factored == false) {
00119
00120
00121
00122 int factor;
00123 factor = pfsfct(n, diag, penv, nblks, xblk, begblk, first, rowblks);
00124 if (factor>0) {
00125 cerr << "In SymArpackSolver: error in factorization.\n";
00126 return -1;
00127 }
00128 factored = true;
00129 }
00130
00131
00132 int nev = theNev;
00133 int ncv = getNCV(n, nev);
00134
00135
00136 int ldv = n;
00137
00138 double *v = new double[ldv * ncv];
00139 double *workl = new double[ncv * (ncv+8)];
00140 double *workd = new double[3 * n];
00141 double *d = new double[ncv * 2];
00142 double *resid = new double[n];
00143
00144
00145 char bmat = 'G';
00146
00147
00148 int *iparam = new int[11];
00149 int *iwork = new int[n];
00150
00151 int lworkl = ncv*ncv + 8*ncv;
00152 int maxitr, mode, nconv;
00153
00154 double tol = 0.0;
00155 int info = 0;
00156 maxitr = 1000;
00157 mode = 3;
00158
00159 iparam[2] = maxitr;
00160 iparam[6] = mode;
00161
00162 bool rvec = true;
00163 char howmy = 'A';
00164 logical *select = new logical[ncv];
00165
00166 iparam[0] = 1;
00167 int ido = 0;
00168 int *ipntr = new int[11];
00169 int ierr = 0;
00170 unsigned int sizeWhich =2;
00171 unsigned int sizeBmat =1;
00172 unsigned int sizeHowmany =1;
00173 while (1) {
00174
00175 #ifdef _WIN32
00176 DSAUPD(&ido, &bmat, &sizeBmat, &n, "LM", &sizeWhich, &nev, &tol, resid,
00177 &ncv, v, &ldv,
00178 iparam, ipntr, workd, workl, &lworkl, &info);
00179 #else
00180 dsaupd_(&ido, &bmat, &n, "LM", &nev, &tol, resid, &ncv, v, &ldv,
00181 iparam, ipntr, workd, workl, &lworkl, &info);
00182 #endif
00183 if (ido == -1) {
00184
00185 myMv(n, &workd[ipntr[0]-1], &workd[ipntr[1]-1]);
00186
00187 pfsslv(n, diag, penv, nblks, xblk, &workd[ipntr[1] - 1], begblk);
00188 continue;
00189 } else if (ido == 1) {
00190 double ratio = 1.0;
00191 myCopy(n, &workd[ipntr[2]-1], &workd[ipntr[1]-1]);
00192
00193 pfsslv(n, diag, penv, nblks, xblk, &workd[ipntr[1] - 1], begblk);
00194
00195 continue;
00196 } else if (ido == 2) {
00197 myMv(n, &workd[ipntr[0]-1], &workd[ipntr[1]-1]);
00198
00199 continue;
00200 }
00201
00202 break;
00203 }
00204
00205 if (info < 0) {
00206 cerr << "BandArpackSolver::Error with _saupd info = " << info <<endl;
00207 return info;
00208 } else {
00209 if (info == 1) {
00210 cerr << "BandArpackSolver::Maximum number of iteration reached." << endl;
00211 } else if (info == 3) {
00212 cerr << "BandArpackSolver::No Shifts could be applied during implicit," << endl;
00213 cerr << "Arnoldi update, try increasing NCV." << endl;
00214 }
00215 double sigma = theSOE->shift;
00216 if (iparam[4] > 0) {
00217 #ifdef _WIN32
00218 DSEUPD(&rvec, &howmy, &sizeHowmany, select, d, v, &ldv, &sigma, &bmat,
00219 &sizeBmat, &n, "LM", &sizeWhich,
00220 &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd,
00221 workl, &lworkl, &info);
00222 #else
00223
00224
00225 dseupd_(&rvec, &howmy, select, d, v, &ldv, &sigma, &bmat, &n, "LM",
00226 &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd,
00227 workl, &lworkl, &info);
00228 #endif
00229 if (info != 0) {
00230 cerr << "BandArpackSolver::Error with dseupd_" << info;
00231 return -1;
00232 }
00233 }
00234 }
00235
00236 value = d;
00237 vector = v;
00238
00239 theSOE->factored = true;
00240
00241 delete [] workl;
00242 delete [] workd;
00243 delete [] resid;
00244 delete [] iparam;
00245 delete [] iwork;
00246 #ifdef _WIN32
00247
00248 #else
00249 delete [] select;
00250 #endif
00251
00252 delete [] ipntr;
00253
00254
00255 return 0;
00256 }
00257
00258
00259 int
00260 SymArpackSolver::setSize()
00261 {
00262
00263
00264 int size = theSOE->size;
00265
00266 if (eigenV == 0 || eigenV->Size() != size) {
00267 if (eigenV != 0)
00268 delete eigenV;
00269
00270 eigenV = new Vector(size);
00271 if (eigenV == 0 || eigenV->Size() != size) {
00272 cerr << "WARNING BandGenLinLapackSolver::setSize() ";
00273 cerr << " - ran out of memory for eigenVector of size ";
00274 cerr << theSOE->size << endl;
00275 return -2;
00276 }
00277 }
00278
00279 return 0;
00280 }
00281
00282 int
00283 SymArpackSolver::setEigenSOE(SymArpackSOE &theEigenSOE)
00284 {
00285 theSOE = &theEigenSOE;
00286 return 0;
00287 }
00288
00289
00290 int
00291 SymArpackSolver::getNCV(int n, int nev)
00292 {
00293 int result;
00294 if (2*nev > nev+8) {
00295 result = nev+8;
00296 } else {
00297 result = 2*nev;
00298 }
00299
00300 if (result >= n) {
00301 result = n;
00302 }
00303
00304 return result;
00305 }
00306
00307
00308 void
00309 SymArpackSolver::myMv(int n, double *v, double *result)
00310 {
00311 double *tempX = new double[n];
00312 int *invp = theSOE->invp;
00313 int i;
00314
00315 for (i=0; i<n; i++) {
00316 tempX[i] = v[invp[i]];
00317 }
00318 for (i=0; i<n; i++) {
00319 v[i] = tempX[i];
00320 }
00321
00322 Vector x(v, n);
00323 Vector y(result,n);
00324
00325 y.Zero();
00326 AnalysisModel *theAnalysisModel = theSOE->theModel;
00327
00328
00329 FE_Element *elePtr;
00330 FE_EleIter &theEles = theAnalysisModel->getFEs();
00331 while((elePtr = theEles()) != 0) {
00332 elePtr->zeroResidual();
00333 elePtr->addM_Force(x,1.0);
00334 const Vector &a = elePtr->getResidual(0);
00335 y.Assemble(a,elePtr->getID(),1.0);
00336
00337
00338 }
00339
00340
00341 Integrator *theIntegrator = 0;
00342 DOF_Group *dofPtr;
00343 DOF_GrpIter &theDofs = theAnalysisModel->getDOFs();
00344 while ((dofPtr = theDofs()) != 0) {
00345 dofPtr->zeroUnbalance();
00346 dofPtr->addM_Force(x,1.0);
00347 const Vector &a = dofPtr->getUnbalance(theIntegrator);
00348 y.Assemble(a,dofPtr->getID(),1.0);
00349 }
00350
00351 for (i=0; i<n; i++) {
00352 tempX[invp[i]] = result[i];
00353 }
00354 for (i=0; i<n; i++) {
00355 result[i] = tempX[i];
00356 }
00357 delete [] tempX;
00358 }
00359
00360 void
00361 SymArpackSolver::myCopy(int n, double *v, double *result)
00362 {
00363 for (int i=0; i<n; i++) {
00364 result[i] = v[i];
00365 }
00366 }
00367
00368 const Vector &
00369 SymArpackSolver::getEigenvector(int mode)
00370 {
00371 int *invp = theSOE->invp;
00372
00373 if (mode <= 0 || mode > theNev) {
00374 cerr << "BandArpackSOE::mode is out of range(1 - nev)";
00375 exit (0);
00376 }
00377 int size = theSOE->size;
00378
00379 int index = (mode - 1) * size;
00380 for (int i=0; i<size; i++) {
00381 (*eigenV)[i] = vector[index + invp[i]];
00382 }
00383
00384 return *eigenV;
00385 }
00386
00387
00388 double
00389 SymArpackSolver::getEigenvalue(int mode)
00390 {
00391 if (mode <= 0 || mode > theNev) {
00392 cerr << "BandArpackSOE::mode is out of range(1 - nev)";
00393 exit (0);
00394 }
00395 return value[mode - 1];
00396 }
00397
00398
00399 int
00400 SymArpackSolver::sendSelf(int cTAg, Channel &theChannel)
00401 {
00402
00403 return 0;
00404 }
00405
00406 int
00407 SymArpackSolver::recvSelf(int cTag,
00408 Channel &theChannel, FEM_ObjectBroker &theBroker)
00409 {
00410
00411 return 0;
00412 }
00413
00414
00415