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