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 #include <DistributedBandGenLinSOE.h>
00031 #include <BandGenLinSolver.h>
00032 #include <Matrix.h>
00033 #include <Graph.h>
00034 #include <Vertex.h>
00035 #include <VertexIter.h>
00036 #include <f2c.h>
00037 #include <math.h>
00038 #include <Channel.h>
00039 #include <FEM_ObjectBroker.h>
00040
00041 DistributedBandGenLinSOE::DistributedBandGenLinSOE(BandGenLinSolver &theSolvr)
00042 :BandGenLinSOE(theSolvr, LinSOE_TAGS_DistributedBandGenLinSOE),
00043 processID(0), numChannels(0), theChannels(0), localCol(0), workArea(0), sizeWork(0), myB(0), myVectB(0)
00044 {
00045 theSolvr.setLinearSOE(*this);
00046 }
00047
00048
00049 DistributedBandGenLinSOE::~DistributedBandGenLinSOE()
00050 {
00051 if (theChannels != 0)
00052 delete [] theChannels;
00053
00054 if (localCol != 0)
00055 for (int i=0; i<numChannels; i++)
00056 if (localCol[i] != 0)
00057 delete localCol[i];
00058 delete [] localCol;
00059
00060 if (workArea != 0)
00061 delete [] workArea;
00062
00063 if (myVectB != 0)
00064 delete myVectB;
00065
00066 if (myB == 0)
00067 delete [] myB;
00068 }
00069
00070
00071 int
00072 DistributedBandGenLinSOE::setSize(Graph &theGraph)
00073 {
00074 int result = 0;
00075 int oldSize = size;
00076 int maxNumSubVertex = 0;
00077
00078
00079 if (processID != 0) {
00080 Channel *theChannel = theChannels[0];
00081 theGraph.sendSelf(0, *theChannel);
00082
00083 static ID data(3);
00084 theChannel->recvID(0, 0, data);
00085 size = data(0);
00086 numSubD = data(1);
00087 numSuperD = data(2);
00088
00089 ID *subMap = new ID(theGraph.getNumVertex());
00090 localCol[0] = subMap;
00091 Vertex *vertex;
00092 VertexIter &theSubVertices = theGraph.getVertices();
00093 int cnt = 0;
00094 while((vertex = theSubVertices()) != 0)
00095 (*subMap)(cnt++) = vertex->getTag();
00096
00097 theChannel->sendID(0, 0, *subMap);
00098 }
00099
00100
00101
00102
00103 else {
00104
00105
00106
00107
00108 FEM_ObjectBroker theBroker;
00109 for (int j=0; j<numChannels; j++) {
00110 Channel *theChannel = theChannels[j];
00111 Graph theSubGraph;
00112 theSubGraph.recvSelf(0, *theChannel, theBroker);
00113 theGraph.merge(theSubGraph);
00114
00115 int numSubVertex = theSubGraph.getNumVertex();
00116 ID *subMap = new ID(numSubVertex);
00117 localCol[j] = subMap;
00118 if (numSubVertex > maxNumSubVertex)
00119 maxNumSubVertex = numSubVertex;
00120 }
00121
00122 size = theGraph.getNumVertex();
00123
00124
00125
00126
00127
00128
00129
00130
00131 numSubD = 0;
00132 numSuperD = 0;
00133
00134 Vertex *vertexPtr;
00135 VertexIter &theVertices = theGraph.getVertices();
00136
00137 while ((vertexPtr = theVertices()) != 0) {
00138 int vertexNum = vertexPtr->getTag();
00139 const ID &theAdjacency = vertexPtr->getAdjacency();
00140 for (int i=0; i<theAdjacency.Size(); i++) {
00141 int otherNum = theAdjacency(i);
00142 int diff = vertexNum - otherNum;
00143 if (diff > 0) {
00144 if (diff > numSuperD)
00145 numSuperD = diff;
00146 } else
00147 if (diff < numSubD)
00148 numSubD = diff;
00149 }
00150 }
00151 numSubD *= -1;
00152
00153 static ID data(3);
00154 data(0) = size;
00155 data(1) = numSubD;
00156 data(2) = numSuperD;
00157
00158
00159
00160
00161 for (int j=0; j<numChannels; j++) {
00162 Channel *theChannel = theChannels[j];
00163 theChannel->sendID(0, 0, data);
00164
00165 ID *subMap = localCol[j];
00166 theChannel->recvID(0, 0, *subMap);
00167 }
00168 }
00169
00170 int numCols = theGraph.getNumVertex();
00171
00172 if (processID != 0) {
00173 ID &globalMap = *(localCol[0]);
00174 ID *localMap = new ID(size);
00175
00176 localMap->Zero();
00177 for (int k=0; k< globalMap.Size(); k++)
00178 (*localMap)(globalMap(k)) = k;
00179 delete localCol[0];
00180 localCol[0] = localMap;
00181 }
00182
00183
00184 int newSize;
00185 if (processID != 0)
00186 newSize = numCols * (2*numSubD + numSuperD + 1);
00187 else
00188 newSize = size * (2*numSubD + numSuperD + 1);
00189
00190
00191
00192 if (newSize != Asize) {
00193
00194 if (processID == 0) {
00195 if (workArea != 0)
00196 delete [] workArea;
00197
00198 workArea = new double [newSize];
00199 sizeWork = newSize;
00200 }
00201 sizeWork = numCols * (2*numSubD + numSuperD +1);
00202
00203 if (A != 0)
00204 delete [] A;
00205
00206 A = new double[newSize];
00207
00208 if (A == 0) {
00209 opserr << "WARNING DistributedBandGenLinSOE::DistributedBandGenLinSOE :";
00210 opserr << " ran out of memory for A (size,super,sub) (";
00211 opserr << size <<", " << numSuperD << ", " << numSubD << ") \n";
00212 Asize = 0; size = 0; numSubD = 0; numSuperD = 0;
00213 result= -1;
00214 }
00215 else
00216 Asize = newSize;
00217 }
00218
00219
00220 for (int i=0; i<Asize; i++)
00221 A[i] = 0;
00222
00223 factored = false;
00224
00225
00226
00227 if (size > Bsize) {
00228
00229
00230 if (B != 0) delete [] B;
00231 if (X != 0) delete [] X;
00232 if (myB != 0) delete [] myB;
00233
00234
00235 B = new double[size];
00236 X = new double[size];
00237 myB = new double[size];
00238
00239 if (B == 0 || X == 0 || myB == 0) {
00240 opserr << "WARNING DistributedBandGenLinSOE::DistributedBandGenLinSOE :";
00241 opserr << " ran out of memory for vectors (size) (";
00242 opserr << size << ") \n";
00243 Bsize = 0; size = 0; numSubD = 0; numSuperD = 0;
00244 result = -1;
00245 }
00246 else
00247 Bsize = size;
00248 }
00249
00250
00251 for (int j=0; j<size; j++) {
00252 B[j] = 0;
00253 X[j] = 0;
00254 myB[j] = 0;
00255 }
00256
00257
00258 if (oldSize != size) {
00259 if (vectX != 0)
00260 delete vectX;
00261
00262 if (vectB != 0)
00263 delete vectB;
00264
00265 if (myVectB != 0)
00266 delete myVectB;
00267
00268 vectX = new Vector(X,size);
00269 vectB = new Vector(B,size);
00270 myVectB = new Vector(myB, size);
00271 }
00272
00273
00274 LinearSOESolver *theSolvr = this->getSolver();
00275 int solverOK = theSolvr->setSize();
00276 if (solverOK < 0) {
00277 opserr << "WARNING:DistributedBandGenLinSOE::setSize :";
00278 opserr << " solver failed setSize()\n";
00279 return solverOK;
00280 }
00281
00282 return result;
00283 }
00284
00285
00286 int
00287 DistributedBandGenLinSOE::addA(const Matrix &m, const ID &id, double fact)
00288 {
00289
00290 if (fact == 0.0) return 0;
00291
00292
00293 int idSize = id.Size();
00294 if (idSize != m.noRows() && idSize != m.noCols()) {
00295 opserr << "BandGenLinSOE::addA() - Matrix and ID not of similar sizes\n";
00296 return -1;
00297 }
00298
00299 int ldA = 2*numSubD + numSuperD + 1;
00300 ID *theMap = 0;
00301 if (numChannels > 0)
00302 theMap = localCol[0];
00303
00304 if (fact == 1.0) {
00305 for (int i=0; i<idSize; i++) {
00306 int col = id(i);
00307 if (col < size && col >= 0) {
00308
00309
00310 double *coliiPtr;
00311 if (processID == 0)
00312 coliiPtr = A + col*ldA + numSubD + numSuperD;
00313 else
00314 coliiPtr = A + ((*theMap)(col))*ldA + numSubD + numSuperD;
00315
00316 for (int j=0; j<idSize; j++) {
00317 int row = id(j);
00318 if (row <size && row >= 0) {
00319 int diff = col - row;
00320 if (diff > 0) {
00321 if (diff <= numSuperD) {
00322 double *APtr = coliiPtr - diff;
00323 *APtr += m(j,i);
00324 }
00325
00326 } else {
00327 diff *= -1;
00328 if (diff <= numSubD) {
00329 double *APtr = coliiPtr + diff;
00330 *APtr += m(j,i);
00331 }
00332 }
00333 }
00334 }
00335 }
00336 }
00337 } else {
00338 for (int i=0; i<idSize; i++) {
00339 int col = id(i);
00340 if (col < size && col >= 0) {
00341
00342
00343 double *coliiPtr;
00344 if (processID == 0)
00345 coliiPtr = A + col*ldA + numSubD + numSuperD;
00346 else
00347 coliiPtr = A + (*theMap)(col)*ldA + numSubD + numSuperD;
00348
00349 for (int j=0; j<idSize; j++) {
00350 int row = id(j);
00351 if (row <size && row >= 0) {
00352 int diff = col - row;
00353 if (diff > 0) {
00354 if (diff <= numSuperD) {
00355 double *APtr = coliiPtr - diff;
00356 *APtr += m(j,i) *fact;
00357 }
00358 } else {
00359 diff *= -1;
00360 if (diff <= numSubD) {
00361 double *APtr = coliiPtr + diff;
00362 *APtr += m(j,i) *fact;
00363 }
00364 }
00365 }
00366 }
00367 }
00368 }
00369 }
00370
00371 return 0;
00372 }
00373
00374 int
00375 DistributedBandGenLinSOE::solve(void)
00376 {
00377 static ID result(1);
00378
00379
00380
00381
00382
00383 if (processID != 0) {
00384 Channel *theChannel = theChannels[0];
00385
00386
00387 theChannel->sendVector(0, 0, *myVectB);
00388
00389
00390
00391 if (factored == false) {
00392 Vector vectA(A, sizeWork);
00393 theChannel->sendVector(0, 0, vectA);
00394 }
00395
00396
00397 theChannel->recvVector(0, 0, *vectX);
00398 theChannel->recvVector(0, 0, *vectB);
00399 theChannel->recvID(0, 0, result);
00400
00401 factored = true;
00402 }
00403
00404
00405
00406
00407
00408 else {
00409
00410
00411 *vectB = *myVectB;
00412
00413
00414 for (int j=0; j<numChannels; j++) {
00415
00416
00417 Channel *theChannel = theChannels[j];
00418 theChannel->recvVector(0, 0, *vectX);
00419 *vectB += *vectX;
00420
00421
00422 if (factored == false) {
00423 const ID &localMap = *(localCol[j]);
00424 int ldA = 2*numSubD + numSuperD + 1;
00425 int localSize = localMap.Size() * ldA;
00426 Vector vectA(workArea, localSize);
00427 theChannel->recvVector(0, 0, vectA);
00428
00429 int loc = 0;
00430 for (int i=0; i<localMap.Size(); i++) {
00431 int pos = localMap(i)*ldA;
00432 for (int k=0; k<ldA; k++)
00433 A[pos++] += workArea[loc++];
00434 }
00435 }
00436 }
00437
00438
00439 result(0) = this->LinearSOE::solve();
00440
00441
00442 for (int j=0; j<numChannels; j++) {
00443 Channel *theChannel = theChannels[j];
00444 theChannel->sendVector(0, 0, *vectX);
00445 theChannel->sendVector(0, 0, *vectB);
00446 theChannel->sendID(0, 0, result);
00447 }
00448 }
00449
00450 return result(0);
00451 }
00452
00453
00454 int
00455 DistributedBandGenLinSOE::addB(const Vector &v, const ID &id, double fact)
00456 {
00457
00458
00459 if (fact == 0.0) return 0;
00460
00461
00462 int idSize = id.Size();
00463 if (idSize != v.Size() ) {
00464 opserr << "BandSPDLinSOE::addB() - Vector and ID not of similar sizes\n";
00465 return -1;
00466 }
00467
00468 if (fact == 1.0) {
00469 for (int i=0; i<idSize; i++) {
00470 int pos = id(i);
00471 if (pos <size && pos >= 0)
00472 myB[pos] += v(i);
00473 }
00474 } else if (fact == -1.0) {
00475 for (int i=0; i<idSize; i++) {
00476 int pos = id(i);
00477 if (pos <size && pos >= 0)
00478 myB[pos] -= v(i);
00479 }
00480 } else {
00481 for (int i=0; i<idSize; i++) {
00482 int pos = id(i);
00483 if (pos <size && pos >= 0)
00484 myB[pos] += v(i) * fact;
00485 }
00486 }
00487 return 0;
00488 }
00489
00490
00491 int
00492 DistributedBandGenLinSOE::setB(const Vector &v, double fact)
00493 {
00494
00495 if (fact == 0.0) return 0;
00496
00497
00498 if (v.Size() != size) {
00499 opserr << "WARNING DistributedBandGenLinSOE::setB() -";
00500 opserr << " incomptable sizes " << size << " and " << v.Size() << endln;
00501 return -1;
00502 }
00503
00504 if (fact == 1.0) {
00505 for (int i=0; i<size; i++) {
00506 myB[i] = v(i);
00507 }
00508 } else if (fact == -1.0) {
00509 for (int i=0; i<size; i++) {
00510 myB[i] = -v(i);
00511 }
00512 } else {
00513 for (int i=0; i<size; i++) {
00514 myB[i] = v(i) * fact;
00515 }
00516 }
00517 return 0;
00518 }
00519
00520 void
00521 DistributedBandGenLinSOE::zeroB(void)
00522 {
00523 double *Bptr = myB;
00524 for (int i=0; i<size; i++)
00525 *Bptr++ = 0;
00526 }
00527
00528
00529 const Vector &
00530 DistributedBandGenLinSOE::getB(void)
00531 {
00532 if (processID != 0) {
00533 Channel *theChannel = theChannels[0];
00534
00535
00536 theChannel->sendVector(0, 0, *myVectB);
00537 theChannel->recvVector(0, 0, *vectB);
00538 }
00539
00540
00541
00542
00543
00544 else {
00545
00546 *vectB = *myVectB;
00547
00548 Vector remoteB(workArea, size);
00549
00550
00551 for (int j=0; j<numChannels; j++) {
00552
00553 Channel *theChannel = theChannels[j];
00554 theChannel->recvVector(0, 0, remoteB);
00555 *vectB += remoteB;
00556 }
00557
00558
00559 for (int j=0; j<numChannels; j++) {
00560 Channel *theChannel = theChannels[j];
00561 theChannel->sendVector(0, 0, *vectB);
00562 }
00563 }
00564
00565 return *vectB;
00566 }
00567
00568
00569 int
00570 DistributedBandGenLinSOE::sendSelf(int commitTag, Channel &theChannel)
00571 {
00572 int sendID =0;
00573
00574
00575
00576
00577
00578
00579 if (processID == 0) {
00580
00581
00582 bool found = false;
00583 for (int i=0; i<numChannels; i++)
00584 if (theChannels[i] == &theChannel) {
00585 sendID = i+1;
00586 found = true;
00587 }
00588
00589
00590 if (found == false) {
00591 int nextNumChannels = numChannels + 1;
00592 Channel **nextChannels = new Channel *[nextNumChannels];
00593 if (nextNumChannels == 0) {
00594 opserr << "DistributedBandGenLinSOE::sendSelf() - failed to allocate channel array of size: " <<
00595 nextNumChannels << endln;
00596 return -1;
00597 }
00598 for (int i=0; i<numChannels; i++)
00599 nextChannels[i] = theChannels[i];
00600 nextChannels[numChannels] = &theChannel;
00601
00602 numChannels = nextNumChannels;
00603
00604 if (theChannels != 0)
00605 delete [] theChannels;
00606
00607 theChannels = nextChannels;
00608
00609 if (localCol != 0)
00610 delete [] localCol;
00611 localCol = new ID *[numChannels];
00612 if (localCol == 0) {
00613 opserr << "DistributedBandGenLinSOE::sendSelf() - failed to allocate id array of size: " <<
00614 nextNumChannels << endln;
00615 return -1;
00616 }
00617 for (int i=0; i<numChannels; i++)
00618 localCol[i] = 0;
00619
00620
00621 sendID = numChannels;
00622 }
00623
00624 } else
00625 sendID = processID;
00626
00627
00628
00629 ID idData(1);
00630 idData(0) = sendID;
00631
00632 int res = theChannel.sendID(0, commitTag, idData);
00633 if (res < 0) {
00634 opserr <<"WARNING DistributedBandGenLinSOE::sendSelf() - failed to send data\n";
00635 return -1;
00636 }
00637
00638 return 0;
00639 }
00640
00641
00642 int
00643 DistributedBandGenLinSOE::recvSelf(int commitTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00644 {
00645 ID idData(1);
00646 int res = theChannel.recvID(0, commitTag, idData);
00647 if (res < 0) {
00648 opserr <<"WARNING DistributedBandGenLinSOE::recvSelf() - failed to send data\n";
00649 return -1;
00650 }
00651 processID = idData(0);
00652
00653 numChannels = 1;
00654 theChannels = new Channel *[1];
00655 theChannels[0] = &theChannel;
00656
00657
00658 localCol = new ID *[numChannels];
00659 for (int i=0; i<numChannels; i++)
00660 localCol[i] = 0;
00661
00662 return 0;
00663 }
00664
00665
00666 int
00667 DistributedBandGenLinSOE::setProcessID(int dTag)
00668 {
00669 processID = dTag;
00670 return 0;
00671 }
00672
00673 int
00674 DistributedBandGenLinSOE::setChannels(int nChannels, Channel **theC)
00675 {
00676 numChannels = nChannels;
00677
00678 if (theChannels != 0)
00679 delete [] theChannels;
00680
00681 theChannels = new Channel *[numChannels];
00682 for (int i=0; i<numChannels; i++)
00683 theChannels[i] = theC[i];
00684
00685
00686 localCol = new ID *[nChannels];
00687 for (int i=0; i<numChannels; i++)
00688 localCol[i] = 0;
00689
00690 return 0;
00691 }