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
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
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
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
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
00165
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;
00172 }
00173
00174
00175
00176
00177
00178
00179 int *rowStartA = new int[size];
00180 int *colA = new int[NNZ];
00181
00182
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();
00198 const ID &theAdjacency = theVertex->getAdjacency();
00199 int idSize = theAdjacency.Size();
00200
00201
00202 for (int i=0; i<idSize; i++) {
00203
00204 int row = theAdjacency(i);
00205 bool foundPlace = false;
00206
00207 for (int j=startLoc; j<lastLoc; j++)
00208 if (colA[j] > row) {
00209
00210
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)
00218 colA[lastLoc] = row;
00219
00220 lastLoc++;
00221 }
00222 rowStartA[a+1] = lastLoc;;
00223 startLoc = lastLoc;
00224 }
00225 }
00226
00227
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);
00236 int *dnnz = new int[numRowsLast];
00237 int *onnz = new int[numRowsLast];
00238
00239
00240 int numRows = numRowsLast;
00241 int endRow = N-1;
00242 int startRow = endRow-numRows +1;
00243
00244 int result = 0;
00245
00246 for (int i=numProcessors-1; i>=0; i--) {
00247
00248
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
00264 if (i != 0) {
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
00282 endRow = startRow-1;
00283 numRows = numRowsTyp;
00284 startRow = endRow-numRows +1;
00285 }
00286
00287
00288
00289
00290 MPI_Bcast(sendBuffer, 3, MPI_INT, 0, PETSC_COMM_WORLD);
00291 result = theSOE.setSizeParallel(numRows, n, dnz, dnnz, onz, onnz);
00292
00293
00294
00295
00296
00297
00298
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
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
00365
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
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