Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

BandArpackSolver.cpp

Go to the documentation of this file.
00001 // File: ~/system_of_eqn/eigenSOE/BandArpackSolver.C
00002 //
00003 // Written: Jun Peng
00004 // Created: Feb. 11, 1999
00005 // Revision: A
00006 //
00007 // Description: This file contains the class definition for 
00008 // BandArpackSolver. It solves the BandArpackSOE object by calling
00009 // Arpack routines.
00010 
00011 #include <BandArpackSolver.h>
00012 #include <BandArpackSOE.h>
00013 #include <f2c.h>
00014 #include <math.h>
00015 #include <stdio.h>
00016 #include <AnalysisModel.h>
00017 #include <DOF_GrpIter.h>
00018 #include <DOF_Group.h>
00019 #include <FE_EleIter.h>
00020 #include <FE_Element.h>
00021 #include <Integrator.h>
00022 
00023 BandArpackSolver::BandArpackSolver(int numE)
00024 :EigenSolver(EigenSOLVER_TAGS_BandArpackSolver),
00025  theNev(numE), iPiv(0), iPivSize(0), eigenV(0)
00026 {
00027   // do nothing here.    
00028 }
00029 
00030 
00031 BandArpackSolver::~BandArpackSolver()
00032 {
00033     if (iPiv != 0)
00034  delete [] iPiv;
00035     if (value != 0)
00036         delete [] value;
00037     if (eigenvector !=0)
00038         delete [] eigenvector;
00039 }
00040 
00041 #ifdef _WIN32
00042 
00043 extern "C" int _stdcall DGBSV(int *N, int *KL, int *KU, int *NRHS, double *A, 
00044          int *LDA, int *iPiv, double *B, int *LDB, 
00045          int *INFO);
00046 
00047 extern "C" int _stdcall DGBTRF(int *M, int *N, int *KL, int *KU, double *A, int *LDA, 
00048           int *iPiv, int *INFO);
00049 
00050 extern "C" int _stdcall DGBTRS(char *TRANS, unsigned int *sizeC, 
00051           int *N, int *KL, int *KU, int *NRHS,
00052           double *A, int *LDA, int *iPiv, 
00053           double *B, int *LDB, int *INFO);
00054 
00055 extern "C" int _stdcall DSAUPD(int *ido, char* bmat, unsigned int *, 
00056           int *n, char *which, unsigned int *,
00057           int *nev, 
00058           double *tol, double *resid, int *ncv, double *v, 
00059           int *ldv,
00060           int *iparam, int *ipntr, double *workd, double *workl,
00061           int *lworkl, int *info);
00062 
00063 extern "C" int _stdcall DSEUPD(bool *rvec, char *howmny, unsigned int *,
00064           logical *select, double *d, double *z,
00065           int *ldz, double *sigma, char *bmat, unsigned int *,
00066           int  *n, char *which, unsigned int *,
00067           int *nev, double *tol, double *resid, int *ncv, 
00068           double *v,
00069           int *ldv, int *iparam, int *ipntr, double *workd, 
00070           double *workl, int *lworkl, int *info);
00071 
00072 #else
00073 
00074 extern "C" int dgbsv_(int *N, int *KL, int *KU, int *NRHS, double *A, int *LDA, 
00075         int *iPiv, double *B, int *LDB, int *INFO);
00076 
00077 extern "C" int dgbtrf_(int *M, int *N, int *KL, int *KU, double *A, int *LDA, 
00078          int *iPiv, int *INFO);
00079          
00080 extern "C" int dgbtrs_(char *TRANS, int *N, int *KL, int *KU, int *NRHS, 
00081          double *A, int *LDA, int *iPiv, double *B, int *LDB, 
00082          int *INFO);
00083 
00084 extern "C" int dsaupd_(int *ido, char* bmat, int *n, char *which, int *nev, 
00085          double *tol, double *resid, int *ncv, double *v, int *ldv,
00086          int *iparam, int *ipntr, double *workd, double *workl,
00087          int *lworkl, int *info);
00088 
00089 extern "C" int dseupd_(bool *rvec, char *howmny, logical *select, double *d, double *z,
00090          int *ldz, double *sigma, char *bmat, int *n, char *which,
00091          int *nev, double *tol, double *resid, int *ncv, double *v,
00092          int *ldv, int *iparam, int *ipntr, double *workd, 
00093          double *workl, int *lworkl, int *info);
00094 
00095 #endif
00096 
00097 
00098 
00099 
00100 int
00101 BandArpackSolver::solve(void)
00102 {
00103 
00104     if (theSOE == 0) {
00105  cerr << "WARNING BandGenLinLapackSolver::solve(void)- ";
00106  cerr << " No LinearSOE object has been set\n";
00107  return -1;
00108     }
00109 
00110     int n = theSOE->size;    
00111     
00112     // check iPiv is large enough
00113     if (iPivSize < n) {
00114  cerr << "WARNING BandGenLinLapackSolver::solve(void)- ";
00115  cerr << " iPiv not large enough - has setSize() been called?\n";
00116  return -1;
00117     }     
00118 
00119     // set some variables
00120     int kl = theSOE->numSubD;
00121     int ku = theSOE->numSuperD;
00122     int ldA = 2*kl + ku +1;
00123     int nrhs = 1;
00124     int ldB = n;
00125     int info;
00126     double *Aptr = theSOE->A;
00127     int    *iPIV = iPiv;
00128 
00129     int nev = theNev;
00130     int ncv = getNCV(n, nev);
00131 
00132     // set up the space for ARPACK functions.
00133     // this is done each time method is called!! .. this needs to be cleaned up
00134     int ldv = n;
00135     int lworkl = ncv*ncv + 8*ncv;
00136     double *v = new double[ldv * ncv];
00137     double *workl = new double[lworkl + 1];
00138     double *workd = new double[3 * n + 1];
00139     double *d = new double[nev];
00140     double *z= new double[n * nev];
00141     double *resid = new double[n];
00142     int *iparam = new int[11];
00143     int *ipntr = new int[11];
00144     logical *select = new logical[ncv];
00145 
00146     static char which[3]; strcpy(which, "LM");
00147     char bmat = 'G';
00148     char howmy = 'A';
00149 
00150     // some more variables
00151     int maxitr, mode;
00152     double tol = 0.0;
00153     info = 0;
00154     maxitr = 1000;
00155     mode = 3;
00156 
00157     iparam[0] = 1;
00158     iparam[2] = maxitr;
00159     iparam[6] = mode; 
00160 
00161     bool rvec = true;
00162 
00163     int ido = 0;
00164 
00165     int ierr = 0;
00166 
00167     // Do the factorization of Matrix (A-dM) here.
00168 #ifdef _WIN32
00169     DGBTRF(&n, &n, &kl, &ku, Aptr, &ldA, iPiv, &ierr); 
00170 #else
00171     dgbtrf_(&n, &n, &kl, &ku, Aptr, &ldA, iPiv, &ierr); 
00172 #endif
00173 
00174     if ( ierr != 0 ) {
00175        cerr << " BandArpackSolver::Error in dgbtrf_ " << endl;
00176        return -1;
00177     }
00178 
00179     while (1) { 
00180 
00181 #ifdef _WIN32
00182       unsigned int sizeWhich =2;
00183       unsigned int sizeBmat =1;
00184       unsigned int sizeHowmany =1;
00185    unsigned int sizeOne = 1;
00186       DSAUPD(&ido, &bmat, &sizeBmat, &n, which, &sizeWhich, &nev, &tol, resid, 
00187       &ncv, v, &ldv,
00188       iparam, ipntr, workd, workl, &lworkl, &info);
00189 #else
00190       dsaupd_(&ido, &bmat, &n, which, &nev, &tol, resid, &ncv, v, &ldv,
00191        iparam, ipntr, workd, workl, &lworkl, &info);
00192 #endif
00193 
00194       if (ido == -1) {
00195 
00196    myMv(n, &workd[ipntr[0]-1], &workd[ipntr[1]-1]); 
00197 #ifdef _WIN32
00198    DGBTRS("N", &sizeOne, &n, &kl, &ku, &nrhs, Aptr, &ldA, iPIV, 
00199    &workd[ipntr[1] - 1], &ldB, &ierr);
00200 #else
00201    dgbtrs_("N", &n, &kl, &ku, &nrhs, Aptr, &ldA, iPIV, 
00202     &workd[ipntr[1] - 1], &ldB, &ierr);
00203 #endif
00204 
00205    if (ierr != 0) {
00206        cerr << "BandArpackSolver::Error with dgbtrs_ 1" <<endl;
00207        exit(0);
00208    }
00209    continue;
00210       } else if (ido == 1) {
00211 
00212  //          double ratio = 1.0;
00213    myCopy(n, &workd[ipntr[2]-1], &workd[ipntr[1]-1]);
00214 
00215 #ifdef _WIN32
00216    DGBTRS("N", &sizeOne, &n, &kl, &ku, &nrhs, Aptr, &ldA, iPIV, 
00217    &workd[ipntr[1] - 1], &ldB, &ierr);
00218 #else
00219    dgbtrs_("N", &n, &kl, &ku, &nrhs, Aptr, &ldA, iPIV, 
00220     &workd[ipntr[1] - 1], &ldB, &ierr);
00221 #endif
00222 
00223    if (ierr != 0) {
00224        cerr << "BandArpackSolver::Error with dgbtrs_ 2" <<endl;
00225        exit(0);
00226    }
00227    continue;
00228       } else if (ido == 2) {     
00229 
00230    myMv(n, &workd[ipntr[0]-1], &workd[ipntr[1]-1]);
00231    continue;
00232       }
00233 
00234       break;
00235     }
00236 
00237     if (info < 0) {
00238       cerr << "BandArpackSolver::Error with _saupd info = " << info << endl;
00239       switch(info) {
00240 
00241          case -1: 
00242     cerr << "N must be positive.\n";
00243     break;
00244          case -2: 
00245     cerr << "NEV must be positive.\n";
00246     break;
00247          case -3: 
00248     cerr << "NCV must be greater than NEV and less than or equal to N.\n";
00249     break;
00250          case -4:
00251     cerr << "The maximum number of Arnoldi update iterations allowed";
00252     break;
00253          case -5: 
00254     cerr << "WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.\n";
00255     break;
00256          case -6: 
00257     cerr << "BMAT must be one of 'I' or 'G'.\n";
00258     break;
00259          case -7: 
00260     cerr << "Length of private work array WORKL is not sufficient.\n";
00261     break;
00262          case -8: 
00263     cerr << "Error return from trid. eigenvalue calculation";
00264     cerr << "Informatinal error from LAPACK routine dsteqr.\n";
00265     break;
00266          case -9: 
00267     cerr << "Starting vector is zero.\n";
00268     break;
00269          case -10: 
00270     cerr << "IPARAM(7) must be 1,2,3,4,5.\n";
00271     break;
00272          case -11: 
00273     cerr << "IPARAM(7) = 1 and BMAT = 'G' are incompatable.\n";
00274     break;
00275          case -12: 
00276     cerr << "IPARAM(1) must be equal to 0 or 1.\n";
00277     break;
00278          case -13:
00279     cerr << "NEV and WHICH = 'BE' are incompatable.\n";
00280     break;
00281          case -9999:
00282     cerr << "Could not build an Arnoldi factorization.";
00283     cerr << "IPARAM(5) returns the size of the current Arnoldi\n";
00284     cerr << "factorization. The user is advised to check that";
00285     cerr << "enough workspace and array storage has been allocated.\n";
00286     break;
00287          default:
00288     cerr << "unrecognised return value\n";
00289       }
00290 
00291       // clean up the memory
00292       delete [] workl;
00293       delete [] workd;
00294       delete [] resid;
00295       delete [] iparam;
00296       delete [] v;
00297       delete [] select;
00298       delete [] ipntr;
00299       delete [] d;
00300       delete [] z;
00301 
00302       value = 0;
00303       eigenvector = 0;
00304   
00305       return info;
00306     } else {
00307         if (info == 1) {
00308    cerr << "BandArpackSolver::Maximum number of iteration reached." << endl;
00309  } else if (info == 3) {
00310    cerr << "BandArpackSolver::No Shifts could be applied during implicit,";
00311    cerr << "Arnoldi update, try increasing NCV." << endl;
00312  }
00313 
00314  double sigma = theSOE->shift;
00315  if (iparam[4] > 0) {
00316      rvec = true;
00317      n = theSOE->size;    
00318      ldv = n;
00319 
00320 #ifdef _WIN32
00321      unsigned int sizeWhich =2;
00322      unsigned int sizeBmat =1;
00323      unsigned int sizeHowmany =1;
00324      DSEUPD(&rvec, &howmy, &sizeHowmany, select, d, z, &ldv, &sigma, &bmat,
00325      &sizeBmat, &n, which, &sizeWhich,
00326      &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd,
00327      workl, &lworkl, &info);
00328 #else
00329      dseupd_(&rvec, &howmy, select, d, z, &ldv, &sigma, &bmat, &n, which,
00330       &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd,
00331       workl, &lworkl, &info);
00332 #endif
00333      if (info != 0) {
00334          cerr << "BandArpackSolver::Error with dseupd_" << info;
00335   switch(info) {
00336 
00337   case -1: 
00338      cerr << " N must be positive.\n";
00339      break;
00340   case -2: 
00341      cerr << " NEV must be positive.\n";
00342      break;
00343   case -3: 
00344      cerr << " NCV must be greater than NEV and less than or equal to N.\n";
00345      break;
00346   case -5: 
00347      cerr << " WHICH must be one of 'LM', 'SM', 'LA', 'SA' or 'BE'.\n";
00348      break;
00349   case -6: 
00350                    cerr << " BMAT must be one of 'I' or 'G'.\n";
00351      break;
00352   case -7: 
00353      cerr << " Length of private work WORKL array is not sufficient.\n";
00354      break;
00355   case -8: 
00356                    cerr << " Error return from trid. eigenvalue calculation";
00357      cerr << "Information error from LAPACK routine dsteqr.\n";
00358      break;
00359   case -9: 
00360                    cerr << " Starting vector is zero.\n";
00361      break;
00362   case -10: 
00363                    cerr << " IPARAM(7) must be 1,2,3,4,5.\n";
00364      break;
00365   case -11: 
00366                    cerr << " IPARAM(7) = 1 and BMAT = 'G' are incompatibl\n";
00367      break;
00368   case -12: 
00369      cerr << " NEV and WHICH = 'BE' are incompatible.\n";
00370      break;
00371   case -14: 
00372      cerr << " DSAUPD did not find any eigenvalues to sufficient accuracy.\n";
00373      break;
00374   case -15: 
00375      cerr << " HOWMNY must be one of 'A' or 'S' if RVEC = .true.\n";
00376      break;
00377   case -16: 
00378      cerr << " HOWMNY = 'S' not yet implemented\n";
00379      break;
00380   default:
00381     ;
00382   }
00383 
00384   // clean up the memory
00385   delete [] workl;
00386   delete [] workd;
00387   delete [] resid;
00388   delete [] iparam;
00389   delete [] v;
00390   delete [] select;
00391   delete [] ipntr;
00392   delete [] d;
00393   delete [] z;
00394 
00395   value = 0;
00396   eigenvector = 0;
00397 
00398   return info;
00399 
00400      }
00401  }
00402     }
00403 
00404 
00405     value = d;
00406     eigenvector = z;
00407 
00408     theSOE->factored = true;
00409 
00410     // clean up the memory
00411     delete [] workl;
00412     delete [] workd;
00413     delete [] resid;
00414     delete [] iparam;
00415     delete [] v;
00416     delete [] select;
00417     delete [] ipntr;
00418 
00419     return 0;
00420 }
00421 
00422 
00423 int 
00424 BandArpackSolver::getNCV(int n, int nev)
00425 {
00426     int result;
00427     if (2*nev > nev+8) {
00428         result = nev+8;
00429     } else {
00430         result = 2*nev;
00431     }
00432 
00433     if (result >= n) {
00434         result = n;
00435     }
00436 
00437     return result;
00438 }
00439 
00440 
00441 void
00442 BandArpackSolver::myMv(int n, double *v, double *result)
00443 {
00444     Vector x(v, n);
00445     Vector y(result,n);
00446 
00447     y.Zero();
00448     AnalysisModel *theAnalysisModel = theSOE->theModel;
00449 
00450     // loop over the FE_Elements
00451     FE_Element *elePtr;
00452     FE_EleIter &theEles = theAnalysisModel->getFEs();    
00453     while((elePtr = theEles()) != 0) {
00454         elePtr->zeroResidual();
00455  elePtr->addM_Force(x,1.0);
00456  const Vector &a = elePtr->getResidual(0);
00457  y.Assemble(a,elePtr->getID(),1.0);
00458  //      const Vector &a = elePtr->getM_Force(x,1.0);
00459  //      y.Assemble(a,elePtr->getID(),1.0);
00460 
00461     }
00462 
00463     // loop over the DOF_Groups
00464     DOF_Group *dofPtr;
00465     DOF_GrpIter &theDofs = theAnalysisModel->getDOFs();
00466     Integrator *theIntegrator = 0;
00467     while ((dofPtr = theDofs()) != 0) {
00468         dofPtr->zeroUnbalance();
00469  dofPtr->addM_Force(x,1.0);
00470  const Vector &a = dofPtr->getUnbalance(theIntegrator);
00471  y.Assemble(a,dofPtr->getID(),1.0);
00472     }
00473 }
00474 
00475 void
00476 BandArpackSolver::myCopy(int n, double *v, double *result)
00477 {
00478     for (int i=0; i<n; i++) {
00479         result[i] = v[i];
00480     }
00481 }
00482 
00483 
00484 int
00485 BandArpackSolver::setEigenSOE(BandArpackSOE &theBandSOE)
00486 {
00487     theSOE = &theBandSOE;
00488     return 0;
00489 }
00490 
00491 
00492 const Vector &
00493 BandArpackSolver::getEigenvector(int mode)
00494 {
00495     if (mode <= 0 || mode > theNev) {
00496         cerr << "BandArpackSOE::getEigenvector() - mode is out of range(1 - nev)";
00497  eigenV->Zero();
00498  return *eigenV;  
00499     }
00500 
00501     int size = theSOE->size;
00502     int index = (mode - 1) * size;
00503 
00504     if (eigenvector != 0) {
00505       for (int i=0; i<size; i++) {
00506  (*eigenV)[i] = eigenvector[index++];
00507       } 
00508     }
00509     else {
00510         cerr << "BandArpackSOE::getEigenvalue() - eigenvectors not yet determined";
00511  eigenV->Zero();
00512     }      
00513 
00514     //Vector *eigenV = new Vector(&vector[index], size);
00515     return *eigenV;  
00516 }
00517 
00518 
00519 double
00520 BandArpackSolver::getEigenvalue(int mode)
00521 {
00522     if (mode <= 0 || mode > theNev) {
00523         cerr << "BandArpackSOE::getEigenvalue() - mode is out of range(1 - nev)";
00524  return -1;
00525     }
00526 
00527     if (value != 0)
00528       return value[mode-1];
00529     else {
00530         cerr << "BandArpackSOE::getEigenvalue() - eigenvalues not yet determined";
00531  return -2;
00532     }      
00533 }
00534   
00535 
00536 int
00537 BandArpackSolver::setSize()
00538 {
00539     // if iPiv not big enough, free it and get one large enough
00540     int size = theSOE->size;    
00541     if (iPivSize < size) {
00542  if (iPiv != 0)
00543      delete [] iPiv;
00544  
00545  iPiv = new int[size];
00546  if (iPiv == 0) {
00547      cerr << "WARNING BandGenLinLapackSolver::setSize() ";
00548      cerr << " - ran out of memory for iPiv of size ";
00549      cerr << theSOE->size << endl;
00550      return -1;
00551  } else
00552      iPivSize = size;
00553     }
00554     
00555     if (eigenV == 0 || eigenV->Size() != size) {
00556  if (eigenV != 0)
00557      delete eigenV;
00558 
00559  eigenV = new Vector(size);
00560  if (eigenV == 0 || eigenV->Size() != size) {
00561      cerr << "WARNING BandGenLinLapackSolver::setSize() ";
00562      cerr << " - ran out of memory for eigenVector of size ";
00563      cerr << theSOE->size << endl;
00564      return -2;     
00565  }
00566     }
00567      
00568     return 0;
00569 }
00570 
00571 
00572 int    
00573 BandArpackSolver::sendSelf(int commitTag, Channel &theChannel)
00574 {
00575     return 0;
00576 }
00577 
00578 int
00579 BandArpackSolver::recvSelf(int commitTag, Channel &theChannel, 
00580       FEM_ObjectBroker &theBroker)
00581 {
00582     // nothing to do
00583     return 0;
00584 }
00585 
00586  
00587 
Copyright Contact Us