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 <ParallelNumberer.h>
00033 #include <AnalysisModel.h>
00034
00035 #include <Domain.h>
00036 #include <ID.h>
00037 #include <Channel.h>
00038 #include <FEM_ObjectBroker.h>
00039 #include <Graph.h>
00040 #include <Vertex.h>
00041 #include <VertexIter.h>
00042 #include <DOF_Group.h>
00043 #include <GraphNumberer.h>
00044 #include <FE_Element.h>
00045 #include <FE_EleIter.h>
00046
00047 ParallelNumberer::ParallelNumberer(int dTag, int numSub, Channel **theC)
00048 :DOF_Numberer(NUMBERER_TAG_ParallelNumberer),
00049 processID(dTag), numChannels(numSub)
00050
00051 {
00052 theChannels = new Channel *[numSub];
00053 for (int i=0; i<numSub; i++)
00054 theChannels[i] = theC[i];
00055 }
00056
00057 ParallelNumberer::ParallelNumberer()
00058 :DOF_Numberer(NUMBERER_TAG_ParallelNumberer), theNumberer(0),
00059 processID(0), numChannels(0), theChannels(0)
00060 {
00061
00062 }
00063
00064
00065 ParallelNumberer::ParallelNumberer(GraphNumberer &theGraphNumberer)
00066 :DOF_Numberer(NUMBERER_TAG_ParallelNumberer), theNumberer(&theGraphNumberer),
00067 processID(0), numChannels(0), theChannels(0)
00068 {
00069
00070 }
00071
00072
00073 ParallelNumberer::~ParallelNumberer()
00074 {
00075 if (theChannels != 0)
00076 delete [] theChannels;
00077
00078 if (theNumberer != 0)
00079 delete theNumberer;
00080 }
00081
00082
00083 int
00084 ParallelNumberer::setProcessID(int dTag)
00085 {
00086 processID = dTag;
00087 return 0;
00088 }
00089
00090 int
00091 ParallelNumberer::setChannels(int nChannels, Channel **theC)
00092 {
00093 numChannels = nChannels;
00094
00095 if (theChannels != 0)
00096 delete [] theChannels;
00097
00098 theChannels = new Channel *[numChannels];
00099 for (int i=0; i<numChannels; i++)
00100 theChannels[i] = theC[i];
00101
00102 return 0;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111 int
00112 ParallelNumberer::numberDOF(int lastDOF)
00113 {
00114 int result = 0;
00115
00116
00117 AnalysisModel *theModel = this->getAnalysisModelPtr();
00118 Domain *theDomain = 0;
00119 if (theModel != 0) theDomain = theModel->getDomainPtr();
00120
00121 if (theModel == 0 || theDomain == 0) {
00122 opserr << "WARNING ParallelNumberer::numberDOF(int) -";
00123 opserr << " - no AnalysisModel - has setLinks() been invoked?\n";
00124 return -1;
00125 }
00126
00127 if (lastDOF != -1) {
00128 opserr << "WARNING ParallelNumberer::numberDOF(int lastDOF):";
00129 opserr << " does not use the lastDOF as requested\n";
00130 }
00131
00132 Graph &theGraph = theModel->getDOFGroupGraph();
00133
00134
00135
00136 if (processID != 0) {
00137
00138 Channel *theChannel = theChannels[0];
00139 int numVertex = theGraph.getNumVertex();
00140
00141
00142
00143
00144
00145
00146 theGraph.sendSelf(0, *theChannel);
00147
00148
00149 ID theID(2*numVertex);
00150 theChannel->recvID(0, 0, theID);
00151
00152
00153 for (int i=0; i<numVertex; i ++) {
00154 int vertexTag = theID(i);
00155 int startID = theID(i+numVertex);
00156
00157 int dofTag = vertexTag;
00158 DOF_Group *dofPtr;
00159 dofPtr = theModel->getDOF_GroupPtr(dofTag);
00160 if (dofPtr == 0) {
00161 opserr << "WARNING ParallelNumberer::numberDOF - ";
00162 opserr << "DOF_Group " << dofTag << "not in AnalysisModel!\n";
00163 result = -4;
00164 } else {
00165 const ID &theDOFID = dofPtr->getID();
00166
00167 int idSize = theDOFID.Size();
00168 for (int j=0; j<idSize; j++)
00169 if (theDOFID(j) == -2 || theDOFID(j) == -3) dofPtr->setID(j, startID++);
00170 }
00171 const ID &theDOFID = dofPtr->getID();
00172 }
00173
00174 theChannel->sendID(0, 0, theID);
00175 }
00176
00177
00178
00179
00180 else {
00181
00182
00183 int numVertex = theGraph.getNumVertex();
00184 int numVertexP0 = numVertex;
00185
00186 ID vertexTags(numVertex);
00187 ID vertexRefs(numVertex);
00188 Vertex *vertexPtr;
00189 int loc = 0;
00190 VertexIter &theVertices = theGraph.getVertices();
00191 while ((vertexPtr = theVertices()) != 0) {
00192 vertexTags[loc] = vertexPtr->getTag();
00193 vertexRefs[loc] = vertexPtr->getRef();
00194 loc++;
00195 }
00196
00197 ID **theSubdomainIDs = new ID *[numChannels];
00198 FEM_ObjectBroker theBroker;
00199
00200
00201
00202
00203
00204
00205 for (int j=0; j<numChannels; j++) {
00206 Channel *theChannel = theChannels[j];
00207 Graph *theSubGraph = new Graph();
00208
00209
00210
00211
00212
00213
00214 theSubGraph->recvSelf(0, *theChannel, theBroker);
00215
00216 theSubdomainIDs[j] = new ID(theSubGraph->getNumVertex()*2);
00217
00218 this->mergeSubGraph(theGraph, *theSubGraph, vertexTags, vertexRefs, *theSubdomainIDs[j]);
00219
00220 delete theSubGraph;
00221 }
00222
00223
00224
00225
00226
00227
00228 ID *theOrderedRefs = new ID(theGraph.getNumVertex());
00229
00230 if (theNumberer != 0) {
00231
00232
00233 *theOrderedRefs = theNumberer->number(theGraph, lastDOF);
00234
00235 } else {
00236
00237
00238
00239 int loc = 0;
00240 for (int l=0; l<numChannels; l++) {
00241 const ID &theSubdomain = *theSubdomainIDs[l];
00242 int numVertexSubdomain = theSubdomain.Size()/2;
00243
00244 for (int i=0; i<numVertexSubdomain; i++) {
00245 int vertexTagMerged = theSubdomain(i+numVertexSubdomain);
00246
00247 if (theOrderedRefs->getLocation(vertexTagMerged) == -1)
00248 (*theOrderedRefs)[loc++] = vertexTagMerged;
00249 }
00250 }
00251
00252
00253 for (int j=0; j<numVertexP0; j++) {
00254 int refTagP0 = vertexTags[j];
00255 if (theOrderedRefs->getLocation(refTagP0) == -1)
00256 (*theOrderedRefs)[loc++] = refTagP0;
00257 }
00258
00259 }
00260
00261
00262 int count = 0;
00263 for (int i=0; i<theOrderedRefs->Size(); i++) {
00264 int vertexTag = (*theOrderedRefs)(i);
00265
00266 Vertex *vertexPtr = theGraph.getVertexPtr(vertexTag);
00267 int numDOF= vertexPtr->getColor();
00268 vertexPtr->setTmp(count);
00269 count += numDOF;
00270 }
00271
00272 if (theNumberer == 0)
00273 delete theOrderedRefs;
00274
00275
00276 for (int i=0; i<numVertexP0; i++ ) {
00277 int vertexTag = vertexTags(i);
00278 Vertex *vertexPtr = theGraph.getVertexPtr(vertexTag);
00279
00280 int startID = vertexPtr->getTmp();
00281 int dofTag = vertexTag;
00282 DOF_Group *dofPtr;
00283 dofPtr = theModel->getDOF_GroupPtr(dofTag);
00284 if (dofPtr == 0) {
00285 opserr << "WARNING ParallelNumberer::numberDOF - ";
00286 opserr << "DOF_Group (P0) " << dofTag << "not in AnalysisModel!\n";
00287 result = -4;
00288 } else {
00289 const ID &theDOFID = dofPtr->getID();
00290 int idSize = theDOFID.Size();
00291 for (int j=0; j<idSize; j++)
00292 if (theDOFID(j) == -2 || theDOFID(j) == -3) dofPtr->setID(j, startID++);
00293 }
00294 }
00295
00296
00297
00298
00299 for (int k=0; k<numChannels; k++) {
00300 Channel *theChannel = theChannels[k];
00301 ID &theSubdomain = *theSubdomainIDs[k];
00302 int numVertexSubdomain = theSubdomain.Size()/2;
00303
00304 for (int i=0; i<numVertexSubdomain; i++) {
00305 int vertexTagMerged = theSubdomain[numVertexSubdomain+i];
00306 Vertex *vertexPtr = theGraph.getVertexPtr(vertexTagMerged);
00307 int startDOF = vertexPtr->getTmp();
00308 theSubdomain[i+numVertexSubdomain] = startDOF;
00309 }
00310
00311 theChannel->sendID(0, 0, theSubdomain);
00312 theChannel->recvID(0, 0, theSubdomain);
00313 delete theSubdomainIDs[k];
00314 }
00315 delete [] theSubdomainIDs;
00316 }
00317
00318
00319 FE_EleIter &theEle = theModel->getFEs();
00320 FE_Element *elePtr;
00321 while ((elePtr = theEle()) != 0)
00322 elePtr->setID();
00323
00324 return result;
00325 }
00326
00327
00328 int
00329 ParallelNumberer::mergeSubGraph(Graph &theGraph, Graph &theSubGraph, ID &vertexTags, ID &vertexRefs, ID &theSubdomainMap)
00330 {
00331
00332
00333
00334
00335
00336 Vertex *subVertexPtr;
00337 VertexIter &theSubGraphIter1 = theSubGraph.getVertices();
00338 int count =0;
00339 int numVertex = theGraph.getNumVertex();
00340 int numVertexSub = theSubGraph.getNumVertex();
00341
00342 while ((subVertexPtr = theSubGraphIter1()) != 0) {
00343 int vertexTagSub = subVertexPtr->getTag();
00344 int vertexTagRef = subVertexPtr->getRef();
00345 int loc = vertexRefs.getLocation(vertexTagRef);
00346
00347 int vertexTagMerged;
00348 if (loc < 0) {
00349
00350 vertexTagMerged = theGraph.getFreeTag();
00351 vertexTags[numVertex] = vertexTagMerged;
00352 vertexRefs[numVertex] = vertexTagRef;
00353 Vertex *newVertex = new Vertex(vertexTagMerged, vertexTagRef, subVertexPtr->getWeight(), subVertexPtr->getColor());
00354
00355 theGraph.addVertex(newVertex);
00356 numVertex++;
00357 } else
00358 vertexTagMerged = vertexTags[loc];
00359
00360
00361 theSubdomainMap[count] = vertexTagSub;
00362 theSubdomainMap[count+numVertexSub] = vertexTagMerged;
00363 count++;
00364 }
00365
00366
00367 VertexIter &theSubGraphIter2 = theSubGraph.getVertices();
00368 while ((subVertexPtr = theSubGraphIter2()) != 0) {
00369 int vertexTagSub = subVertexPtr->getTag();
00370 int loc = theSubdomainMap.getLocation(vertexTagSub);
00371 int vertexTagMerged = theSubdomainMap[loc+numVertexSub];
00372
00373 const ID &adjacency = subVertexPtr->getAdjacency();
00374
00375 for (int i=0; i<adjacency.Size(); i++) {
00376 int vertexTagSubAdjacent = adjacency(i);
00377 int loc = theSubdomainMap.getLocation(vertexTagSubAdjacent);
00378 int vertexTagMergedAdjacent = theSubdomainMap[loc+numVertexSub];
00379 theGraph.addEdge(vertexTagMerged, vertexTagMergedAdjacent);
00380 }
00381 }
00382
00383
00384 return 0;
00385 }
00386
00387
00388 int
00389 ParallelNumberer::sendSelf(int cTag, Channel &theChannel)
00390 {
00391 int sendID =0;
00392
00393
00394
00395
00396
00397
00398 if (processID == 0) {
00399
00400
00401 bool found = false;
00402 for (int i=0; i<numChannels; i++)
00403 if (theChannels[i] == &theChannel) {
00404 sendID = i+1;
00405 found = true;
00406 }
00407
00408
00409 if (found == false) {
00410 int nextNumChannels = numChannels + 1;
00411 Channel **nextChannels = new Channel *[nextNumChannels];
00412 if (nextNumChannels == 0) {
00413 opserr << "ParalellNumberer::sendSelf() - failed to allocate channel array of size: " <<
00414 nextNumChannels << endln;
00415 return -1;
00416 }
00417 for (int i=0; i<numChannels; i++)
00418 nextChannels[i] = theChannels[i];
00419 nextChannels[numChannels] = &theChannel;
00420
00421 numChannels = nextNumChannels;
00422
00423 if (theChannels != 0)
00424 delete [] theChannels;
00425
00426 theChannels = nextChannels;
00427
00428
00429 sendID = numChannels;
00430 }
00431
00432 } else
00433 sendID = processID;
00434
00435
00436
00437 ID idData(1);
00438 idData(0) = sendID;
00439
00440 int res = theChannel.sendID(0, cTag, idData);
00441 if (res < 0) {
00442 opserr <<"WARNING DistributedSparseGenColLinSOE::sendSelf() - failed to send data\n";
00443 return -1;
00444 }
00445
00446 return 0;
00447 }
00448
00449 int
00450 ParallelNumberer::recvSelf(int cTag,
00451 Channel &theChannel,
00452 FEM_ObjectBroker &theBroker)
00453 {
00454 ID idData(1);
00455 int res = theChannel.recvID(0, cTag, idData);
00456 if (res < 0) {
00457 opserr <<"WARNING Parallel::recvSelf() - failed to send data\n";
00458 return -1;
00459 }
00460 processID = idData(0);
00461
00462 numChannels = 1;
00463 theChannels = new Channel *[1];
00464 theChannels[0] = &theChannel;
00465
00466 return 0;
00467 }
00468
00469
00470 int
00471 ParallelNumberer::numberDOF(ID &lastDOFs)
00472 {
00473
00474 int result = 0;
00475
00476
00477 AnalysisModel *theModel = this->getAnalysisModelPtr();
00478 Domain *theDomain = 0;
00479 if (theModel != 0) theDomain = theModel->getDomainPtr();
00480
00481 if (theModel == 0 || theDomain == 0) {
00482 opserr << "WARNING ParallelNumberer::numberDOF(int) -";
00483 opserr << " - no AnalysisModel - has setLinks() been invoked?\n";
00484 return -1;
00485 }
00486
00487 Graph &theGraph = theModel->getDOFGroupGraph();
00488
00489
00490
00491 if (processID != 0) {
00492 Channel *theChannel = theChannels[0];
00493 int numVertex = theGraph.getNumVertex();
00494 theGraph.sendSelf(0, *theChannel);
00495 ID theID(2*numVertex);
00496 theChannel->recvID(0, 0, theID);
00497 for (int i=0; i<numVertex; i += 2) {
00498 int dofTag = theID(i);
00499 int startID = theID(i+1);
00500 DOF_Group *dofPtr;
00501 dofPtr = theModel->getDOF_GroupPtr(dofTag);
00502 if (dofPtr == 0) {
00503 opserr << "WARNING ParallelNumberer::numberDOF - ";
00504 opserr << "DOF_Group " << dofTag << "not in AnalysisModel!\n";
00505 result = -4;
00506 } else {
00507 const ID &theID = dofPtr->getID();
00508 int idSize = theID.Size();
00509 for (int j=0; j<idSize; j++)
00510 if (theID(j) == -2) dofPtr->setID(j, startID++);
00511 }
00512 }
00513 }
00514
00515
00516
00517
00518 else {
00519
00520
00521 int numVertex = theGraph.getNumVertex();
00522 ID vertexTags(numVertex);
00523 ID vertexRefs(numVertex);
00524 Vertex *vertexPtr;
00525 int loc = 0;
00526 VertexIter &theVertices = theGraph.getVertices();
00527 while ((vertexPtr = theVertices()) != 0) {
00528 vertexTags[loc] = vertexPtr->getTag();
00529 vertexRefs[loc] = vertexPtr->getRef();
00530 loc++;
00531 }
00532
00533 ID **theSubdomainIDs = new ID *[numChannels];
00534 FEM_ObjectBroker theBroker;
00535
00536
00537 for (int j=0; j<numChannels; j++) {
00538 Channel *theChannel = theChannels[j];
00539 Graph theSubGraph;
00540 theSubGraph.recvSelf(0, *theChannel, theBroker);
00541 theSubdomainIDs[j] = new ID(theSubGraph.getNumVertex()*2);
00542 this->mergeSubGraph(theGraph, theSubGraph, vertexTags, vertexRefs, *theSubdomainIDs[j]);
00543 }
00544
00545
00546
00547
00548
00549 for (int k=0; k<numChannels; k++) {
00550 Channel *theChannel = theChannels[k];
00551
00552 theChannel->sendID(0, 0, *theSubdomainIDs[k]);
00553 delete theSubdomainIDs[k];
00554 }
00555 delete [] theSubdomainIDs;
00556
00557
00558 }
00559
00560 return result;
00561 }