DistributedSuperLU.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020                                                                         
00021 // $Revision: 1.1 $
00022 // $Date: 2005/12/06 22:21:03 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/system_of_eqn/linearSOE/sparseGEN/DistributedSuperLU.cpp,v $
00024                                                                         
00025                                                                         
00026 // Written: fmk 
00027 //
00028 // Description: This file contains the implementation of DistributedSuperLU
00029 //
00030 // What: "@(#) DistributedSuperLU.h, revA"
00031 
00032 #include <DistributedSuperLU.h>
00033 #include <SparseGenColLinSOE.h>
00034 #include <f2c.h>
00035 #include <math.h>
00036 #include <Channel.h>
00037 #include <FEM_ObjectBroker.h>
00038 #include <ID.h>
00039 
00040 DistributedSuperLU::DistributedSuperLU(int npR, int npC)
00041   :SparseGenColLinSolver(SOLVER_TAGS_DistributedSuperLU), 
00042    gridInit(false), npRow(npR), npCol(npC),
00043    processID(0), numChannels(0), theChannels(0)
00044 {
00045 
00046 }
00047 
00048 
00049 DistributedSuperLU::DistributedSuperLU()
00050   :SparseGenColLinSolver(SOLVER_TAGS_DistributedSuperLU), 
00051    gridInit(false), npRow(0), npCol(0),
00052    processID(0), numChannels(0), theChannels(0)
00053 {
00054 
00055 }
00056 
00057 
00058 DistributedSuperLU::~DistributedSuperLU()
00059 {
00060   //Destroy_LU(theSOE->size, &grid, &LUstruct); 
00061   ScalePermstructFree(&ScalePermstruct);
00062   LUstructFree(&LUstruct); 
00063 
00064   //superlu_gridexit(&grid);
00065 
00066   if (theChannels != 0)
00067     delete [] theChannels;
00068 
00069   //  MPI_Comm_free(&comm_SuperLU);
00070 }
00071 
00072 int
00073 DistributedSuperLU::solve(void)
00074 {
00075   if (theSOE == 0) {
00076     opserr << "WARNING DistributedSuperLU::solve(void)- ";
00077     opserr << " No LinearSOE object has been set\n";
00078     return -1;
00079   }
00080 
00081   // check for quick return
00082   if (theSOE->size == 0)
00083     return 0;
00084 
00085   // if subprocess recv A & B from p0
00086   if (processID != 0) {
00087     Channel *theChannel = theChannels[0];
00088     theChannel->recvVector(0, 0, (*theSOE->vectB));
00089     Vector vectA(theSOE->A, theSOE->nnz);    
00090     theChannel->recvVector(0, 0, vectA);
00091   } 
00092 
00093   //
00094   // if main process, send B & A to all, solve and send back X, B & result
00095 
00096 
00097   else {
00098 
00099     Vector vectA(theSOE->A, theSOE->nnz);    
00100 
00101     // send B & A to p1 through n-1
00102     for (int j=0; j<numChannels; j++) {
00103       Channel *theChannel = theChannels[j];
00104       theChannel->sendVector(0, 0, *(theSOE->vectB));
00105       theChannel->sendVector(0, 0, vectA);
00106     }
00107   }
00108 
00109   int info;
00110 
00111   int iam = grid.iam;
00112 
00113   if (iam < (npRow * npCol)) {
00114     int n = theSOE->size;
00115     int nnz = theSOE->nnz;
00116     int ldb = n;
00117     int nrhs = 1;
00118     static double berr[1];
00119 
00120     // first copy B into X
00121     double *Xptr = theSOE->X;
00122     double *Bptr = theSOE->B;
00123 
00124     for (int i=0; i<n; i++)
00125       *(Xptr++) = *(Bptr++);
00126     Xptr = theSOE->X;
00127 
00128     //
00129     // set the Fact options:
00130     //   leave DOFACT if never been factored
00131     //   otherwise use SamePattern if factored at least once
00132     //
00133 
00134     if ((options.Fact == FACTORED) && (theSOE->factored == false)) {
00135       options.Fact = SamePattern;
00136       for (int i=0; i<nnz; i++) rowA[i] = theSOE->rowA[i];
00137     }
00138 
00139     //
00140     // solve & mark as factored
00141     //
00142 
00143     pdgssvx_ABglobal(&options, &A, &ScalePermstruct, Xptr, ldb, nrhs, &grid,
00144                      &LUstruct, berr, &stat, &info);
00145 
00146     if (theSOE->factored == false) {
00147       options.Fact = FACTORED;      
00148       theSOE->factored = true;
00149     }
00150   }
00151 
00152   /*
00153   // synch processes again
00154   if (processID != 0) {
00155     static ID idData(1); 
00156     idData(0) = info;
00157     Channel *theChannel = theChannels[0];
00158     theChannel->sendID(0, 0, idData);
00159   } 
00160   else {
00161     for (int j=0; j<numChannels; j++) {
00162       static ID idData(1);
00163       Channel *theChannel = theChannels[j];
00164       theChannel->recvID(0, 0, idData);
00165     }
00166   }
00167   */
00168 
00169   return 0;
00170 }
00171 
00172 int
00173 DistributedSuperLU::setSize()
00174 {
00175   int n = theSOE->size;
00176 
00177   //
00178   // init the super lu process grid
00179   //
00180   if (gridInit == false) {
00181 
00182     MPI_Comm  comm_world;  //
00183     MPI_Group group_world; // group_worker;
00184 
00185     comm_world = MPI_COMM_WORLD;
00186     MPI_Comm_group(comm_world, &group_world);
00187     //    MPI_Group_excl(group_world, 1, 0, &group_worker);  /* process 0 not member */
00188 
00189     MPI_Comm_create(comm_world, group_world, &comm_SuperLU);
00190 
00191     superlu_gridinit(comm_SuperLU, npRow, npCol, &grid);
00192 
00193   // free old structures if resize already called
00194   } else {
00195     Destroy_LU(theSOE->size, &grid, &LUstruct); 
00196     ScalePermstructFree(&ScalePermstruct);
00197     LUstructFree(&LUstruct); 
00198   }
00199   
00200   //
00201   // Initialize the statistics variables.
00202   //
00203   PStatInit(&stat);
00204   
00205   //
00206   // Create compressed column matrix for A. 
00207   //
00208                               
00209   if (n > 0) {
00210     
00211     // create the SuperMatrix A 
00212     int nnz = theSOE->nnz;
00213     rowA = new int[nnz];
00214     for (int i=0; i<nnz; i++) rowA[i] = theSOE->rowA[i];
00215 
00216     dCreate_CompCol_Matrix_dist(&A, n, n, nnz, theSOE->A, 
00217                                 rowA, theSOE->colStartA, 
00218                                 SLU_NC, SLU_D, SLU_GE);
00219 
00220 
00221     //
00222     // Initialize ScalePermstruct and LUstruct.
00223     //
00224     ScalePermstructInit(n, n, &ScalePermstruct);
00225     LUstructInit(n, n, &LUstruct);
00226   }  
00227                               
00228                               
00229   //
00230   //  set default options
00231   //
00232   set_default_options_Distributed(&options);    
00233 
00234   //
00235   // Initialize the statistics variables. 
00236   //
00237   PStatInit(&stat);
00238 
00239   return 0;
00240 }
00241 
00242 
00243 int
00244 DistributedSuperLU::setProcessID(int dTag) 
00245 {
00246   processID = dTag;
00247   return 0;
00248 }
00249 
00250 int
00251 DistributedSuperLU::setChannels(int nChannels, Channel **theC)
00252 {
00253   numChannels = nChannels;
00254 
00255   if (theChannels != 0)
00256     delete [] theChannels;
00257 
00258   theChannels = new Channel *[numChannels];
00259   if (theChannels == 0) {
00260     opserr << "DistributedSuperLU::sendSelf() - failed to allocate channel array of size: " << 
00261       numChannels << endln;
00262     return -1;
00263   }
00264 
00265   for (int i=0; i<numChannels; i++)
00266     theChannels[i] = theC[i];
00267 
00268   return 0;
00269 }
00270 
00271 int
00272 DistributedSuperLU::sendSelf(int cTag, Channel &theChannel)
00273 {
00274   int sendID =0;
00275 
00276   // if P0 check if already sent. If already sent use old processID; if not allocate a new process 
00277   // id for remote part of object, enlarge channel * to hold a channel * for this remote object.
00278 
00279   // if not P0, send current processID
00280 
00281   if (processID == 0) {
00282 
00283     // check if already using this object
00284     bool found = false;
00285     for (int i=0; i<numChannels; i++)
00286       if (theChannels[i] == &theChannel) {
00287         sendID = i+1;
00288         found = true;
00289       }
00290 
00291     // if new object, enlarge Channel pointers to hold new channel * & allocate new ID
00292     if (found == false) {
00293       int nextNumChannels = numChannels + 1;
00294       Channel **nextChannels = new Channel *[nextNumChannels];
00295       if (nextNumChannels == 0) {
00296         opserr << "DistributedSuperLU::sendSelf() - failed to allocate channel array of size: " << 
00297           nextNumChannels << endln;
00298         return -1;
00299       }
00300       for (int i=0; i<numChannels; i++)
00301         nextChannels[i] = theChannels[i];
00302       nextChannels[numChannels] = &theChannel;
00303       
00304       numChannels = nextNumChannels;
00305       
00306       if (theChannels != 0)
00307         delete [] theChannels;
00308       
00309       theChannels = nextChannels;
00310       
00311       // allocate new processID for remote object
00312       sendID = numChannels;
00313     }
00314 
00315   } else 
00316     sendID = processID;
00317 
00318   static ID idData(3);
00319   idData(0) = sendID;
00320   idData(1) = npRow;
00321   idData(2) = npCol;
00322   int res = theChannel.sendID(0, cTag, idData);
00323   if (res < 0) {
00324     opserr <<"WARNING DistributedSuperLU::sendSelf() - failed to send data\n";
00325     return -1;
00326   }           
00327   return 0;
00328 }
00329 
00330 int
00331 DistributedSuperLU::recvSelf(int cTag, 
00332                              Channel &theChannel, 
00333                              FEM_ObjectBroker &theBroker)
00334 {
00335   static ID idData(3);
00336 
00337   int res = theChannel.recvID(0, cTag, idData);
00338   if (res < 0) {
00339     opserr <<"WARNING DistributedSuperLU::recvSelf() - failed to receive data\n";
00340     return -1;
00341   }           
00342 
00343   processID = idData(0);
00344   npRow = idData(1);
00345   npCol = idData(2);
00346 
00347   numChannels = 1;
00348   theChannels = new Channel *[1];
00349   theChannels[0] = &theChannel;
00350 
00351   return 0;
00352 }
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 

Generated on Mon Oct 23 15:05:29 2006 for OpenSees by doxygen 1.5.0