ShadowPetscSOE.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.2 $
00022 // $Date: 2003/02/14 23:02:02 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/system_of_eqn/linearSOE/petsc/ShadowPetscSOE.cpp,v $
00024                                                                         
00025                                                                         
00026 // File: ~/system_of_eqn/linearSOE/petsc/ShadowPetscSOE.C
00027 //
00028 // Written: fmk & om
00029 // Created: 7/98
00030 // Revision: A
00031 //
00032 // Description: This file contains the implementation for BandGenLinSOE
00033 
00034 #include <string.h>
00035 #include "ShadowPetscSOE.h"
00036 #include "PetscSolver.h"
00037 #include <Matrix.h>
00038 #include <Graph.h>
00039 #include <Vertex.h>
00040 #include <VertexIter.h>
00041 #include <f2c.h>
00042 #include <math.h>
00043 #include <Channel.h>
00044 #include <FEM_ObjectBroker.h>
00045 
00046 ShadowPetscSOE::ShadowPetscSOE(PetscSolver &theSOESolver, int bs)
00047 :LinearSOE(theSOESolver, LinSOE_TAGS_ShadowPetscSOE),
00048  theSOE(theSOESolver, bs), theSolver(&theSOESolver), myRank(0),
00049  sendBuffer(0), blockSize(bs)
00050 {
00051 
00052   MPI_Comm_rank(PETSC_COMM_WORLD, &myRank);
00053   MPI_Comm_size(PETSC_COMM_WORLD, &numProcessors);
00054   // MPI_Comm_dup(PETSC_COMM_WORLD, &theComm);
00055   if (myRank != 0) {
00056     opserr << " ShadowPetscSOE::ShadowPetscSOE - must be rank 0\n";
00057   }
00058   sendBuffer = (void *)(&sendData[0]);
00059   MPI_Barrier(PETSC_COMM_WORLD);
00060 
00061 /************
00062   // send data on the PetscSolver
00063   int petscMethod;
00064   int petscPre;
00065 
00066   KSPType method = theSOESolver.method;
00067   PCType preconditioner = theSOESolver.preconditioner;
00068 
00069   if (strcmp(method,KSPCG) == 0)
00070     petscMethod = 1;
00071   else if (strcmp(method,KSPGMRES) == 0)
00072     petscMethod = 2;
00073   else if (strcmp(method,KSPBCGS) == 0)
00074     petscMethod = 3;
00075   else if (strcmp(method,KSPCGS) == 0)
00076     petscMethod = 4;
00077   else if (strcmp(method,KSPTFQMR) == 0)
00078     petscMethod = 5;
00079   else if (strcmp(method,KSPTCQMR) == 0)
00080     petscMethod = 6;
00081   else if (strcmp(method,KSPCR) == 0)
00082     petscMethod = 7;
00083   else if (strcmp(method, KSPLSQR) == 0)
00084     petscMethod = 8;
00085   else if (strcmp(method, KSPRICHARDSON) == 0)
00086     petscMethod = 9;
00087   else if (strcmp(method,KSPCHEBYCHEV) == 0)
00088     petscMethod = 10;
00089   else if (strcmp(method, KSPPREONLY) == 0)
00090     petscMethod = 11;
00091   else {
00092     opserr << "ShadowPetscSOE::ShadowPetscSOE - unknown KSP method\n";
00093     petscMethod = 12;
00094   }
00095 
00096   if (strcmp(preconditioner,PCNONE) == 0)
00097     petscPre = 1;
00098   else if (strcmp(preconditioner,PCJACOBI) == 0)
00099     petscPre = 2;
00100   else if (strcmp(preconditioner,PCSOR) == 0)
00101     petscPre = 3;
00102   else if (strcmp(preconditioner,PCEISENSTAT) == 0)
00103     petscPre = 4;
00104   else if (strcmp(preconditioner,PCBJACOBI) == 0)
00105     petscPre = 5;
00106   else if (strcmp(preconditioner,PCASM) == 0)
00107     petscPre = 6;
00108   else if (strcmp(preconditioner,PCILU) == 0)
00109     petscPre = 7;
00110   else if (strcmp(preconditioner,PCICC) == 0)
00111     petscPre = 8;  
00112   else if (strcmp(preconditioner,PCBGS) == 0)
00113     petscPre = 9;
00114   else if (strcmp(preconditioner,PCMG) == 0)
00115     petscPre = 10;
00116   else if (strcmp(preconditioner,PCSHELL) == 0)
00117     petscPre = 11;
00118   else if (strcmp(preconditioner,PCLU) == 0)
00119     petscPre = 12;
00120   else {
00121     opserr << "ActorPetscSOE::ActorPetscSOE - unknown PC method\n";
00122     petscPre = 13;
00123   }
00124 
00125   // now send the data to the remote actor objects
00126   sendData[0] = petscMethod;
00127   sendData[1] = petscPre;
00128   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);    
00129 **********/
00130 
00131 }
00132 
00133 
00134 int
00135 ShadowPetscSOE::getNumEqn(void) const
00136 {
00137     return theSOE.size;
00138 }
00139     
00140 ShadowPetscSOE::~ShadowPetscSOE()
00141 {
00142   sendData[0] = 0;
00143   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00144   MPI_Barrier(PETSC_COMM_WORLD);
00145 }
00146 
00147 
00148 int 
00149 ShadowPetscSOE::solve(void)
00150 {
00151   sendData[0] = 1;
00152   sendData[1] = theSOE.isFactored;
00153   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00154   return theSOE.solve();
00155 }
00156 
00157 int 
00158 ShadowPetscSOE::setSize(Graph &theGraph)
00159 {
00160   int n = theGraph.getNumVertex();
00161   int size = n;
00162   int N = n;
00163 
00164   // fist itearte through the vertices of the graph to get nnz,
00165   // the number of non-zeros.
00166   Vertex *theVertex;
00167   int NNZ = 0;
00168   VertexIter &theVertices = theGraph.getVertices();
00169   while ((theVertex = theVertices()) != 0) {
00170     const ID &theAdjacency = theVertex->getAdjacency();
00171     NNZ += theAdjacency.Size() +1; // the +1 is for the diag entry
00172   }
00173 
00174   // we determine the number of non-zeros & number of nonzero's
00175   // in each row of A
00176   // create two integer arrays. One containing the column indices for each
00177   // entry in A stored in order by row and column number. 
00178   // The other a pointer into this array for each row.
00179   int *rowStartA = new int[size];  // start locations of rows in colA
00180   int *colA = new int[NNZ]; // column locations, stored row-wise
00181 
00182   // fill in rowStartA and colA
00183   if (size != 0) {
00184     rowStartA[0] = 0;
00185     int startLoc = 0;
00186     int lastLoc = 0;
00187     for (int a=0; a<size; a++) {
00188 
00189       theVertex = theGraph.getVertexPtr(a);
00190       if (theVertex == 0) {
00191         opserr << "WARNING:SparseGenLinSOE::setSize :";
00192         opserr << " vertex " << a << " not in graph! - size set to 0\n";
00193         size = 0;
00194         return -1;
00195       }
00196 
00197       colA[lastLoc++] = theVertex->getTag(); // place diag in first
00198       const ID &theAdjacency = theVertex->getAdjacency();
00199       int idSize = theAdjacency.Size();
00200         
00201       // now we have to place the entries in the ID into order in colA
00202       for (int i=0; i<idSize; i++) {
00203 
00204         int row = theAdjacency(i);
00205         bool foundPlace = false;
00206         // find a place in colA for current col
00207         for (int j=startLoc; j<lastLoc; j++)
00208           if (colA[j] > row) { 
00209             // move the entries already there one further on
00210             // and place col in current location
00211             for (int k=lastLoc; k>j; k--)
00212               colA[k] = colA[k-1];
00213             colA[j] = row;
00214             foundPlace = true;
00215               j = lastLoc;
00216           }
00217         if (foundPlace == false) // put in at the end
00218           colA[lastLoc] = row;
00219 
00220         lastLoc++;
00221       }
00222       rowStartA[a+1] = lastLoc;;            
00223       startLoc = lastLoc;
00224     }
00225   }
00226 
00227   // now for each of the SOE's we determine how to invoke setSizeParallel()
00228   sendData[0] = 2;
00229   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00230 
00231   int dnz = 0;
00232   int onz = 0;
00233   int numRowsTyp = N/blockSize/numProcessors;
00234   numRowsTyp *= blockSize;
00235   int numRowsLast = numRowsTyp + (N - numProcessors*numRowsTyp); // lastProc extra rows
00236   int *dnnz = new int[numRowsLast];
00237   int *onnz = new int[numRowsLast];
00238 
00239   // first determine start and end rows of diag block
00240   int numRows = numRowsLast;
00241   int endRow = N-1;
00242   int startRow = endRow-numRows +1; 
00243   
00244   int result = 0;
00245   // we have to go last to first
00246   for (int i=numProcessors-1; i>=0; i--) {
00247 
00248     // for each processor determine onnz and dnnz info in colA[]
00249     for (int j=0; j<numRows; j++) {
00250       dnnz[j] = 0; 
00251       onnz[j] = 0;
00252       int rowStart = rowStartA[startRow+j];
00253       int nextRowStart = rowStartA[startRow+j+1];
00254       for (int k=rowStart; k<nextRowStart; k++) {
00255         int col = colA[k];
00256         if (col < startRow || col > endRow)
00257           onnz[j] += 1;
00258         else
00259           dnnz[j] += 1;
00260       }
00261     }
00262 
00263     // now send the data
00264     if (i != 0) {  // remote object
00265       sendData[0] = 2;
00266       sendData[1] = numRows;
00267       sendData[2] = n;
00268       
00269       int tag = 100;
00270       MPI_Send(sendBuffer, 3, MPI_INT, i, tag, PETSC_COMM_WORLD);
00271 
00272       tag = 101;
00273       void *buffer = (void *)dnnz;
00274       MPI_Send(buffer, numRows, MPI_INT, i, tag, PETSC_COMM_WORLD);
00275 
00276       tag = 102;
00277       buffer = (void *)onnz;
00278       MPI_Send(buffer, numRows, MPI_INT, i, tag, PETSC_COMM_WORLD);
00279     }      
00280 
00281     // increment startRow, endRow and numRows if necessary
00282     endRow = startRow-1;
00283     numRows = numRowsTyp;
00284     startRow = endRow-numRows +1; 
00285   }
00286 
00287   // we broadcast again before we start setSizeParallel()
00288   // this is because Petsc all processes need to call setup at same
00289   // time .. if don't we hang
00290   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);  
00291   result = theSOE.setSizeParallel(numRows, n, dnz, dnnz, onz, onnz);
00292 
00293   // free up trhe memory used
00294   /*
00295   delete [] colA;
00296   delete [] rowStartA;
00297   delete [] onnz;
00298   delete [] dnnz;
00299   */
00300 
00301   return result;
00302 }
00303 
00304 
00305 
00306 int 
00307 ShadowPetscSOE::addA(const Matrix &m, const ID &id, double fact)
00308 {
00309   return theSOE.addA(m, id, fact);
00310 }
00311 
00312     
00313 int 
00314 ShadowPetscSOE::addB(const Vector &v, const ID &id, double fact)
00315 {
00316   return theSOE.addB(v, id, fact);
00317 }
00318 
00319 
00320 int
00321 ShadowPetscSOE::setB(const Vector &v, double fact)
00322 {
00323   return theSOE.setB(v, fact);
00324 }
00325 
00326 
00327 void 
00328 ShadowPetscSOE::zeroA(void)
00329 {
00330   sendData[0] = 3;
00331   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00332   theSOE.zeroA();
00333 }
00334         
00335 void 
00336 ShadowPetscSOE::zeroB(void)
00337 {
00338   sendData[0] = 4;
00339   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00340   theSOE.zeroB();
00341 }
00342 
00343 
00344 const Vector &
00345 ShadowPetscSOE::getX(void)
00346 {
00347   sendData[0] = 5;
00348   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00349 
00350 
00351   double *theData =0;
00352   double *X = theSOE.X;
00353 
00354   // put the local data into the X array
00355   int high, low;
00356   int ierr = VecGetOwnershipRange(theSOE.x, &low, &high);CHKERRA(ierr);       
00357 
00358   ierr = VecGetArray(theSOE.x, &theData); CHKERRA(ierr);       
00359   opserr << "ShadowPetscSOE::getX - low:high " << low << " " << high << endln;
00360   for (int i=low; i<=high; i++)
00361     X[i] = theData[i-low];
00362   ierr = VecRestoreArray(theSOE.x, &theData); CHKERRA(ierr);             
00363 
00364   // now from each actor object get it's local copy
00365   // and place in the array
00366   int tag = 99;
00367   for (i=1; i<numProcessors; i++) {
00368     MPI_Status status;
00369     MPI_Recv(sendBuffer, 3, MPI_INT, i, tag, PETSC_COMM_WORLD, &status);
00370     low = sendData[0];
00371     high = sendData[1];
00372   opserr << "ShadowPetscSOE::getX - low:high " << low << " " << high << endln;
00373     double *dataBuf = &X[low];
00374     void *buffer = (void *)dataBuf;
00375     MPI_Recv(buffer, high-low, MPI_DOUBLE, i, tag, PETSC_COMM_WORLD, &status);
00376   }
00377 
00378   return *(theSOE.vectX);
00379 }
00380 
00381 
00382 const Vector &
00383 ShadowPetscSOE::getB(void)
00384 {
00385   sendData[0] = 6;
00386   MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00387 
00388   // STOP ****** some more work here
00389   return theSOE.getB();
00390 }
00391 
00392 
00393 double 
00394 ShadowPetscSOE::normRHS(void)
00395 {
00396   theSOE.getB();
00397   double norm =0.0;
00398   int size = theSOE.size;
00399   double *Bptr = theSOE.B;
00400   for (int i=0; i<size; i++) {
00401     double Yi = *Bptr++;
00402     norm += Yi*Yi;
00403   }
00404   return sqrt(norm);
00405 }    
00406 
00407 
00408 void 
00409 ShadowPetscSOE::setX(int loc, double value)
00410 {
00411   theSOE.setX(loc, value);
00412 }
00413 
00414 int
00415 ShadowPetscSOE::setSolver(PetscSolver &newSolver)
00416 {
00417   opserr << "ShadowPetscSOE::setSolver - not yet working\n";
00418   return -1;
00419 }
00420 
00421 
00422 int 
00423 ShadowPetscSOE::sendSelf(int cTag, Channel &theChannel)
00424 {
00425   opserr << "WARNING ShadowPetscSOE::sendSelf - does not send itself YET\n";
00426   return 0;
00427 }
00428 
00429 
00430 int 
00431 ShadowPetscSOE::recvSelf(int cTag, 
00432                          Channel &theChannel, FEM_ObjectBroker &theBroker)
00433 {
00434   opserr << "WARNING ShadowPetscSOE::sendSelf - does not receive itself YET\n";
00435   return 0;
00436 }
00437 
00438 
00439 
00440 
00441 

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