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 #include "PetscSOE.h"
00033 #include "PetscSolver.h"
00034 #include <petscvec.h>
00035 #include <Matrix.h>
00036 #include <Graph.h>
00037 #include <Vertex.h>
00038 #include <VertexIter.h>
00039 #include <f2c.h>
00040 #include <math.h>
00041 #include <Channel.h>
00042 #include <FEM_ObjectBroker.h>
00043
00044 PetscSOE::PetscSOE(PetscSolver &theSOESolver, int bs)
00045 :LinearSOE(theSOESolver, LinSOE_TAGS_PetscSOE),
00046 isFactored(0),size(0), processID(0), numProcesses(0), B(0), X(0),
00047 indices(0), vectX(0), vectB(0), A(0), x(0), b(0), blockSize(bs),
00048 numChannels(0), theChannels(0), localCol(0)
00049 {
00050 theSOESolver.setLinearSOE(*this);
00051 }
00052
00053
00054 int
00055 PetscSOE::getNumEqn(void) const
00056 {
00057 return size;
00058 }
00059
00060 PetscSOE::~PetscSOE()
00061 {
00062 if (theChannels != 0)
00063 delete [] theChannels;
00064
00065 if (localCol != 0)
00066 for (int i=0; i<numChannels; i++)
00067 if (localCol[i] != 0)
00068 delete localCol[i];
00069 delete [] localCol;
00070
00071 if (vectX != 0) delete vectX;
00072 if (vectB != 0) delete vectB;
00073
00074 if (B != 0) delete [] B;
00075 if (X != 0) delete [] X;
00076
00077
00078 if (A != 0) MatDestroy(A);
00079 if (b != 0) VecDestroy(b);
00080 if (x != 0) VecDestroy(x);
00081 }
00082
00083
00084 int
00085 PetscSOE::setSize(Graph &theGraph)
00086 {
00087 PetscInitialize(0, PETSC_NULL, (char *)0, PETSC_NULL);
00088 MPI_Comm_size(PETSC_COMM_WORLD, &numProcesses);
00089 MPI_Comm_rank(PETSC_COMM_WORLD, &processID);
00090
00091 int result = 0;
00092 int ierr = 0;
00093
00094
00095
00096
00097
00098 if (numProcesses == 1) {
00099
00100
00101 size = theGraph.getNumVertex();
00102 isFactored = 0;
00103
00104 } else {
00105
00106
00107 size = 0;
00108 isFactored = 0;
00109 VertexIter &theVertices = theGraph.getVertices();
00110 Vertex *theVertex;
00111 while ((theVertex = theVertices()) != 0) {
00112 int vertexTag = theVertex->getTag();
00113 if (vertexTag > size)
00114 size = vertexTag;
00115 }
00116
00117 static ID data(1);
00118
00119
00120
00121
00122 if (processID != 0) {
00123 Channel *theChannel = theChannels[0];
00124
00125 data(0) = size;
00126 theChannel->sendID(0, 0, data);
00127 theChannel->recvID(0, 0, data);
00128
00129 size = data(0);
00130 } else {
00131
00132 for (int j=0; j<numChannels; j++) {
00133 Channel *theChannel = theChannels[j];
00134 theChannel->recvID(0, 0, data);
00135 if (data(0) > size)
00136 size = data(0);
00137 }
00138 data(0) = size;
00139 for (int j=0; j<numChannels; j++) {
00140 Channel *theChannel = theChannels[j];
00141 theChannel->sendID(0, 0, data);
00142 }
00143 }
00144 size = size+1;
00145 }
00146
00147
00148 if (A != 0) MatDestroy(A);
00149 if (b != 0) VecDestroy(b);
00150 if (x != 0) VecDestroy(x);
00151
00152
00153
00154
00155
00156
00157 if (B != 0) delete [] B;
00158 if (X != 0) delete [] X;
00159
00160
00161 B = new double[size];
00162 X = new double[size];
00163
00164 if (B == 0 || X == 0) {
00165 opserr << "WARNING PetscSOE::PetscSOE :";
00166 opserr << " ran out of memory for vectors (size) (";
00167 opserr << size << ") \n";
00168 size = 0;
00169 result = -1;
00170 }
00171
00172
00173 for (int j=0; j<size; j++) {
00174 B[j] = 0;
00175 X[j] = 0;
00176 }
00177
00178 if (vectX != 0)
00179 delete vectX;
00180
00181 if (vectB != 0)
00182 delete vectB;
00183
00184 vectX = new Vector(X, size);
00185 vectB = new Vector(B, size);
00186
00187
00188
00189
00190
00191 if (numProcesses == 1) {
00192
00193
00194
00195 int *rowA = new int[size];
00196
00197
00198 int NNZ = 0;
00199 for (int a=0; a<size; a++) {
00200 Vertex *theVertex = theGraph.getVertexPtr(a);
00201 if (theVertex == 0) {
00202 opserr << "WARNING:PetscSOE::setSize :";
00203 opserr << " vertex " << a << " not in graph! - size set to 0\n";
00204 size = 0;
00205 return -1;
00206 }
00207
00208 const ID &theAdjacency = theVertex->getAdjacency();
00209 int idSize = theAdjacency.Size();
00210
00211 NNZ += idSize +1;
00212 rowA[a] = idSize +1;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 if (blockSize == 1) {
00222 ierr = MatCreateSeqAIJ(PETSC_COMM_SELF, size, size, 0, rowA, &A); CHKERRQ(ierr);
00223 } else {
00224 ierr = MatCreateSeqBAIJ(PETSC_COMM_SELF, blockSize, size,size, 0, rowA, &A); CHKERRQ(ierr);
00225 }
00226
00227 ierr = VecCreateSeqWithArray(PETSC_COMM_WORLD, size, X, &x); CHKERRQ(ierr);
00228 ierr = VecCreateSeqWithArray(PETSC_COMM_WORLD, size, B, &b); CHKERRQ(ierr);
00229
00230
00231 LinearSOESolver *tSolver = this->getSolver();
00232 int solverOK = tSolver->setSize();
00233 if (solverOK < 0) {
00234 opserr << "WARNING:PetscSOE::setSize :";
00235 opserr << " solver failed setSize()\n";
00236 return solverOK;
00237 }
00238
00239
00240 delete [] rowA;
00241
00242
00243 } else {
00244
00245
00246
00247
00248
00249
00250 ierr = PetscOptionsGetInt(PETSC_NULL, "-n", &size, &flg); CHKERRQ(ierr);
00251 ierr = MatCreate(PETSC_COMM_WORLD, PETSC_DECIDE, PETSC_DECIDE,size, size, &A); CHKERRQ(ierr);
00252 ierr = MatSetFromOptions(A);CHKERRQ(ierr);
00253 ierr = MatGetOwnershipRange(A, &startRow, &endRow);CHKERRQ(ierr);
00254
00255 ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD, endRow-startRow, size, &X[startRow], &x); CHKERRQ(ierr);
00256 ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD, endRow-startRow, size, &B[startRow], &b); CHKERRQ(ierr);
00257
00258
00259 LinearSOESolver *tSolver = this->getSolver();
00260 int solverOK = tSolver->setSize();
00261 if (solverOK < 0) {
00262 opserr << "WARNING:PetscSOE::setSize :";
00263 opserr << " solver failed setSize()\n";
00264 return solverOK;
00265 }
00266 }
00267
00268 return result;
00269 }
00270
00271
00272 int
00273 PetscSOE::addA(const Matrix &m, const ID &id, double fact)
00274 {
00275 isFactored = 0;
00276
00277
00278 if (fact == 0.0) return 0;
00279
00280
00281
00282 int idSize = id.Size();
00283 if (idSize != m.noRows() && idSize != m.noCols()) {
00284 opserr << "PetscSOE::addA() - Matrix and ID not of similar sizes\n";
00285 return -1;
00286 }
00287
00288 int n = id.Size();
00289 int row;
00290 int col;
00291 double value;
00292 for (int i=0; i<n; i++) {
00293 row = id(i);
00294 if (row >= 0) {
00295 for (int j=0; j<n; j++) {
00296 col = id(j);
00297 if (col >= 0) {
00298 value = m(i,j)*fact;
00299 int ierr = MatSetValues(A,1,&row,1,&col,&value,ADD_VALUES);
00300 if (ierr) opserr << processID << " " << row << " " << col << endln;
00301 CHKERRQ(ierr);
00302 }
00303 }
00304 }
00305 }
00306
00307 return 0;
00308 }
00309
00310
00311 int
00312 PetscSOE::addB(const Vector &v, const ID &id, double fact)
00313 {
00314
00315 if (fact == 0.0) return 0;
00316
00317
00318
00319 int idSize = id.Size();
00320 if (idSize != v.Size() ) {
00321 opserr << "BandGenLinSOE::addB() - Vector and ID not of similar sizes\n";
00322 return -1;
00323 }
00324
00325 if (fact == 1.0) {
00326 for (int i=0; i<idSize; i++) {
00327 int pos = id(i);
00328 if (pos <size && pos >= 0)
00329 B[pos] += v(i);
00330 }
00331 } else if (fact == -1.0) {
00332 for (int i=0; i<idSize; i++) {
00333 int pos = id(i);
00334 if (pos <size && pos >= 0)
00335 B[pos] -= v(i);
00336 }
00337 } else {
00338 for (int i=0; i<idSize; i++) {
00339 int pos = id(i);
00340 if (pos <size && pos >= 0)
00341 B[pos] += v(i) * fact;
00342 }
00343 }
00344 return 0;
00345 }
00346
00347
00348 int
00349 PetscSOE::setB(const Vector &v, double fact)
00350 {
00351
00352 if (fact == 0.0) return 0;
00353
00354
00355 if (v.Size() != size) {
00356 opserr << "WARNING BandGenLinSOE::setB() -";
00357 opserr << " incomptable sizes " << size << " and " << v.Size() << endln;
00358 return -1;
00359 }
00360
00361 if (fact == 1.0) {
00362 for (int i=0; i<size; i++) {
00363 B[i] = v(i);
00364 }
00365 } else if (fact == -1.0) {
00366 for (int i=0; i<size; i++) {
00367 B[i] = -v(i);
00368 }
00369 } else {
00370 for (int i=0; i<size; i++) {
00371 B[i] = v(i) * fact;
00372 }
00373 }
00374 return 0;
00375 }
00376
00377
00378 void
00379 PetscSOE::zeroA(void)
00380 {
00381 isFactored = 0;
00382 MatZeroEntries(A);
00383 }
00384
00385 void
00386 PetscSOE::zeroB(void)
00387 {
00388 double *Bptr = B;
00389 for (int i=0; i<size; i++)
00390 *Bptr++ = 0;
00391 }
00392
00393
00394 const Vector &
00395 PetscSOE::getX(void)
00396 {
00397 if (vectX == 0) {
00398 opserr << "FATAL PetscSOE::getX - vectX == 0!";
00399 exit(-1);
00400 }
00401 return *vectX;
00402 }
00403
00404
00405 const Vector &
00406 PetscSOE::getB(void)
00407 {
00408 static Vector recvVector(1);
00409 static Vector myVectorB(1);
00410
00411 if (vectB == 0) {
00412 opserr << "FATAL PetscSOE::getB - vectB == 0!";
00413 exit(-1);
00414 }
00415
00416 if (numProcesses > 1) {
00417 if (myVectorB.Size() != size)
00418 myVectorB.resize(size);
00419
00420 if (processID != 0) {
00421 Channel *theChannel = theChannels[0];
00422
00423 theChannel->sendVector(0, 0, *vectB);
00424 theChannel->recvVector(0, 0, myVectorB);
00425 } else {
00426 if (recvVector.Size() != size)
00427 recvVector.resize(size);
00428
00429 myVectorB = *vectB;
00430 for (int j=0; j<numChannels; j++) {
00431 Channel *theChannel = theChannels[j];
00432 theChannel->recvVector(0, 0, recvVector);
00433 myVectorB += recvVector;
00434 }
00435 for (int j=0; j<numChannels; j++) {
00436 Channel *theChannel = theChannels[j];
00437 theChannel->sendVector(0, 0, myVectorB);
00438 }
00439 }
00440 return myVectorB;
00441
00442 } else
00443 return *vectB;
00444 }
00445
00446
00447 double
00448 PetscSOE::normRHS(void)
00449 {
00450 this->getB();
00451 double norm =0.0;
00452 double *Bptr = B;
00453 for (int i=0; i<size; i++) {
00454 double Yi = *Bptr++;
00455 norm += Yi*Yi;
00456 }
00457 return sqrt(norm);
00458 }
00459
00460
00461 void
00462 PetscSOE::setX(int loc, double value)
00463 {
00464 if (loc < size && loc >= 0)
00465 X[loc] = value;
00466 }
00467
00468 void
00469 PetscSOE::setX(const Vector &xData)
00470 {
00471 if (xData.Size() == size && vectX != 0)
00472 *vectX = xData;
00473 }
00474
00475 int
00476 PetscSOE::setSolver(PetscSolver &newSolver)
00477 {
00478 newSolver.setLinearSOE(*this);
00479
00480 if (size != 0) {
00481 int solverOK = newSolver.setSize();
00482 if (solverOK < 0) {
00483 opserr << "WARNING:PetscSOE::setSolver :";
00484 opserr << "the new solver could not setSeize() - staying with old\n";
00485 return solverOK;
00486 }
00487 }
00488
00489 return this->LinearSOE::setSolver(newSolver);
00490 }
00491
00492
00493 int
00494 PetscSOE::sendSelf(int cTag, Channel &theChannel)
00495 {
00496 processID = 0;
00497 int sendID =0;
00498
00499
00500
00501
00502
00503
00504 if (processID == 0) {
00505
00506
00507 bool found = false;
00508 for (int i=0; i<numChannels; i++)
00509 if (theChannels[i] == &theChannel) {
00510 sendID = i+1;
00511 found = true;
00512 }
00513
00514
00515 if (found == false) {
00516 int nextNumChannels = numChannels + 1;
00517 Channel **nextChannels = new Channel *[nextNumChannels];
00518 if (nextNumChannels == 0) {
00519 opserr << "DistributedBandGenLinSOE::sendSelf() - failed to allocate channel array of size: " <<
00520 nextNumChannels << endln;
00521 return -1;
00522 }
00523 for (int i=0; i<numChannels; i++)
00524 nextChannels[i] = theChannels[i];
00525 nextChannels[numChannels] = &theChannel;
00526 numChannels = nextNumChannels;
00527
00528 if (theChannels != 0)
00529 delete [] theChannels;
00530
00531 theChannels = nextChannels;
00532
00533 if (localCol != 0)
00534 delete [] localCol;
00535 localCol = new ID *[numChannels];
00536 if (localCol == 0) {
00537 opserr << "DistributedBandGenLinSOE::sendSelf() - failed to allocate id array of size: " <<
00538 nextNumChannels << endln;
00539 return -1;
00540 }
00541 for (int i=0; i<numChannels; i++)
00542 localCol[i] = 0;
00543
00544
00545 sendID = numChannels;
00546 }
00547
00548 } else
00549 sendID = processID;
00550
00551 return 0;
00552 }
00553
00554
00555 int
00556 PetscSOE::recvSelf(int cTag, Channel &theChannel,
00557 FEM_ObjectBroker &theBroker)
00558 {
00559 numChannels = 1;
00560 theChannels = new Channel *[1];
00561 theChannels[0] = &theChannel;
00562
00563 localCol = new ID *[numChannels];
00564 for (int i=0; i<numChannels; i++)
00565 localCol[i] = 0;
00566
00567 return 0;
00568 }
00569
00570 int
00571 PetscSOE::setChannels(int nChannels, Channel **theC)
00572 {
00573 numChannels = nChannels;
00574
00575 if (theChannels != 0)
00576 delete [] theChannels;
00577
00578 theChannels = new Channel *[numChannels];
00579 for (int i=0; i<numChannels; i++)
00580 theChannels[i] = theC[i];
00581
00582
00583 localCol = new ID *[nChannels];
00584 for (int i=0; i<numChannels; i++)
00585 localCol[i] = 0;
00586
00587 return 0;
00588 }