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
00035
00036
00037
00038
00039
00040 #include <Metis.h>
00041 #include <Graph.h>
00042 #include <Vertex.h>
00043 #include <VertexIter.h>
00044
00045
00046 #include <bool.h>
00047
00048
00049
00050 extern "C"
00051 int PMETIS(int *, int *, int *, int *, int *, int *, int *, int *, int *, int *, int *);
00052
00053 extern "C"
00054 int KMETIS(int *, int *, int *, int *, int *, int *, int *, int *, int *, int *, int *);
00055
00056 Metis::Metis(int numParts)
00057 :GraphNumberer(GraphNUMBERER_TAG_Metis),
00058 myPtype(0), myMtype(0), myCoarsenTo(0), myRtype(0), myIPtype(0),
00059 defaultOptions(true), numPartitions(numParts), theRefResult(0)
00060 {
00061
00062 }
00063
00064 Metis::Metis(int Ptype,
00065 int Mtype,
00066 int coarsenTo,
00067 int Rtype,
00068 int IPtype,
00069 int numParts)
00070 :GraphNumberer(GraphNUMBERER_TAG_Metis),
00071 myPtype(Ptype), myMtype(Mtype), myCoarsenTo(coarsenTo), myRtype(Rtype),
00072 myIPtype(IPtype), defaultOptions(false), numPartitions(numParts), theRefResult(0)
00073 {
00074
00075 checkOptions();
00076 }
00077
00078
00079 Metis::~Metis()
00080 {
00081
00082 }
00083
00084 bool
00085 Metis::setOptions(int Ptype,
00086 int Mtype,
00087 int coarsenTo,
00088 int Rtype,
00089 int IPtype)
00090 {
00091 myPtype=Ptype;
00092 myMtype = Mtype;
00093 myCoarsenTo = coarsenTo;
00094 myRtype = Rtype;
00095 myIPtype = IPtype;
00096
00097 defaultOptions = false;
00098
00099 return checkOptions();
00100
00101 }
00102
00103
00104
00105
00106
00107 bool
00108 Metis::checkOptions(void)
00109 {
00110
00111
00112
00113 if (defaultOptions == true)
00114 return true;
00115
00116
00117
00118 bool okFlag = true;
00119
00120 if ((myPtype != 1) || (myPtype != 2)) {
00121 okFlag = false;
00122 opserr << "WARNING: Metis::partition ";
00123 opserr << " - Illegal Ptype " << myPtype << endln;
00124 }
00125
00126 if ((myMtype != 1) || (myMtype != 2) || (myMtype != 3) ||
00127 ((myMtype != 4) || (myMtype != 5) || myMtype != 11) ||
00128 (myMtype != 21) || (myMtype != 51)) {
00129 okFlag = false;
00130 opserr << "WARNING: Metis::partition ";
00131 opserr << " - Illegal Mtype " << myMtype << endln;
00132 }
00133
00134 if (myPtype == 1)
00135 if ((myRtype != 1) || (myRtype != 2) || (myRtype != 3) ||
00136 (myRtype != 11) || (myRtype != 12) || (myRtype != 13) ||
00137 (myRtype != 20)) {
00138 okFlag = false;
00139 opserr << "WARNING: Metis::partition ";
00140 opserr << " - Illegal Rtype " << myRtype << endln;
00141 opserr << " for Ptype " << myPtype << endln;
00142 }
00143 else
00144 if (myPtype == 2)
00145 if ((myRtype != 11) || (myRtype != 12) || (myRtype != 20)) {
00146 okFlag = false;
00147 opserr << "WARNING: Metis::partition ";
00148 opserr << " - Illegal Rtype " << myRtype << endln;
00149 opserr << " for Ptype " << myPtype << endln;
00150 }
00151
00152 if ((myIPtype != 1) || (myIPtype != 2) || (myIPtype != 3) ||
00153 (myIPtype != 4)) {
00154 okFlag = false;
00155 opserr << "WARNING: Metis::partition ";
00156 opserr << " - Illegal IPtype " << myIPtype << endln;
00157 }
00158
00159 if (myCoarsenTo < 0) {
00160 okFlag = false;
00161 opserr << "WARNING: Metis::partition ";
00162 opserr << " - Illegal coarsen To " << myCoarsenTo << endln;
00163 }
00164
00165 if (okFlag == false)
00166 defaultOptions = true;
00167
00168 return okFlag;
00169
00170 }
00171
00172
00173 bool
00174 Metis::setDefaultOptions(void)
00175 {
00176 defaultOptions = true;
00177 return true;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 int
00189 Metis::partition(Graph &theGraph, int numPart)
00190 {
00191 if (theGraph.getNumVertex() == numPart) {
00192 Vertex *vertex;
00193 int current = 1;
00194 VertexIter &theVertices = theGraph.getVertices();
00195 while ((vertex = theVertices()) != 0)
00196 vertex->setColor(current++);
00197
00198 return 0;
00199 }
00200
00201
00202 if (checkOptions() == false)
00203 return -1;
00204
00205
00206
00207 int numVertex = theGraph.getNumVertex();
00208 int numEdge = theGraph.getNumEdge();
00209
00210 int *options = new int [5];
00211 int *partition = new int [numVertex+1];
00212 int *xadj = new int [numVertex+2];
00213 int *adjncy = new int [2*numEdge];
00214 int *vwgts = 0;
00215 int *ewgts = 0;
00216 int numbering = 0;
00217 int weightflag = 0;
00218
00219 if (START_VERTEX_NUM == 0)
00220 numbering = 0;
00221 else if (START_VERTEX_NUM == 1)
00222 numbering = 1;
00223 else {
00224 opserr << "WARNING Metis::partition - No partitioning done";
00225 opserr << " vertex numbering must start at 0 or 1\n";
00226 return (-2);
00227 }
00228 int edgecut;
00229
00230 if ((options == 0) || (partition == 0) || (xadj == 0) || (adjncy == 0)) {
00231 opserr << "WARNING Metis::partition - No partitioning done";
00232 opserr << " as ran out of memory\n";
00233 return (-2);
00234 }
00235
00236
00237
00238
00239 int indexEdge = 0;
00240 xadj[0] = 0;
00241
00242 Vertex *vertexPtr;
00243 for (int vertex =0; vertex<numVertex; vertex++) {
00244 vertexPtr = theGraph.getVertexPtr(vertex+START_VERTEX_NUM);
00245
00246
00247
00248
00249 if (vertexPtr == 0) {
00250 opserr << "WARNING Metis::partition - No partitioning done";
00251 opserr << " Metis requires consequtive Vertex Numbering\n";
00252
00253 delete [] options;
00254 delete [] partition;
00255 delete [] xadj;
00256 delete [] adjncy;
00257
00258 return -2;
00259 }
00260
00261 const ID&adjacency = vertexPtr->getAdjacency();
00262 int degree = adjacency.Size();
00263 for (int i=0; i<degree; i++) {
00264 adjncy[indexEdge++] = adjacency(i)-START_VERTEX_NUM;
00265 }
00266
00267 xadj[vertex+1] = indexEdge;
00268 }
00269
00270 if (defaultOptions == true)
00271 options[0] = 0;
00272 else {
00273 options[0] =1;
00274 options[1] = myCoarsenTo;
00275 options[2] = myMtype;
00276 options[3] = myIPtype;
00277 options[4] = myRtype;
00278 }
00279
00280
00281
00282 if (myPtype == 1)
00283 PMETIS(&numVertex, xadj, adjncy, vwgts, ewgts, &weightflag, &numPart,
00284 options, &numbering, &edgecut, partition);
00285 else
00286 KMETIS(&numVertex, xadj, adjncy, vwgts, ewgts, &weightflag, &numPart,
00287 options, &numbering, &edgecut, partition);
00288
00289
00290 for (int vert =0; vert<numVertex; vert++) {
00291 vertexPtr = theGraph.getVertexPtr(vert+START_VERTEX_NUM);
00292 vertexPtr->setColor(partition[vert]+1);
00293 }
00294
00295
00296
00297 delete [] options;
00298 delete [] partition;
00299 delete [] xadj;
00300 delete [] adjncy;
00301
00302 return 0;
00303 }
00304
00305
00306
00307
00308
00309
00310 const ID &
00311 Metis::number(Graph &theGraph, int lastVertex)
00312 {
00313
00314
00315 int numVertex = theGraph.getNumVertex();
00316
00317 if (theRefResult != 0)
00318 delete theRefResult;
00319
00320 theRefResult = new ID(numVertex);
00321
00322 if (theRefResult == 0) {
00323 opserr << "ERROR: Metis::number - Out of Memory\n";
00324 theRefResult = new ID(0);
00325 return *theRefResult;
00326 }
00327
00328 if (checkOptions() == false) {
00329 opserr << "ERROR: Metis::number - chek options failed\n";
00330 return *theRefResult;
00331 }
00332
00333
00334 int numEdge = theGraph.getNumEdge();
00335
00336 int *options = new int [5];
00337 int *partition = new int [numVertex+1];
00338 int *xadj = new int [numVertex+2];
00339 int *adjncy = new int [2*numEdge];
00340 int *vwgts = 0;
00341 int *ewgts = 0;
00342 int numbering = 0;
00343 int weightflag = 0;
00344
00345 if (START_VERTEX_NUM == 0)
00346 numbering = 0;
00347 else if (START_VERTEX_NUM == 1)
00348 numbering = 1;
00349 else {
00350 opserr << "WARNING Metis::partition - No partitioning done";
00351 opserr << " vertex numbering must start at 0 or 1\n";
00352 return *theRefResult;
00353 }
00354 int edgecut;
00355
00356 if ((options == 0) || (partition == 0) || (xadj == 0) || (adjncy == 0)) {
00357 opserr << "WARNING Metis::partition - No partitioning done";
00358 opserr << " as ran out of memory\n";
00359 return *theRefResult;
00360 }
00361
00362
00363
00364
00365 int indexEdge = 0;
00366 xadj[0] = 0;
00367
00368 Vertex *vertexPtr;
00369 for (int vertex =0; vertex<numVertex; vertex++) {
00370 vertexPtr = theGraph.getVertexPtr(vertex+START_VERTEX_NUM);
00371
00372
00373
00374
00375 if (vertexPtr == 0) {
00376 opserr << "WARNING Metis::partition - No partitioning done";
00377 opserr << " Metis requires consequtive Vertex Numbering\n";
00378
00379 delete [] options;
00380 delete [] partition;
00381 delete [] xadj;
00382 delete [] adjncy;
00383
00384 return *theRefResult;
00385 }
00386
00387 const ID&adjacency = vertexPtr->getAdjacency();
00388 int degree = adjacency.Size();
00389 for (int i=0; i<degree; i++) {
00390 adjncy[indexEdge++] = adjacency(i)-START_VERTEX_NUM;
00391 }
00392
00393 xadj[vertex+1] = indexEdge;
00394 }
00395
00396
00397 if (defaultOptions == true)
00398 options[0] = 0;
00399 else {
00400 options[0] =1;
00401 options[1] = myCoarsenTo;
00402 options[2] = myMtype;
00403 options[3] = myIPtype;
00404 options[4] = myRtype;
00405 }
00406
00407
00408
00409
00410 if (myPtype == 1)
00411
00412 PMETIS(&numVertex, xadj, adjncy, vwgts, ewgts, &weightflag,
00413 &numPartitions, options, &numbering, &edgecut, partition);
00414 else
00415 KMETIS(&numVertex, xadj, adjncy, vwgts, ewgts, &weightflag,
00416 &numPartitions, options, &numbering, &edgecut, partition);
00417
00418 opserr << "Metis::number -2\n";
00419
00420
00421
00422
00423 int count = 0;
00424 for (int i=0; i<numPartitions; i++) {
00425 for (int vert=0; vert<numVertex; vert++) {
00426 if (partition[vert] == i) {
00427 vertexPtr = theGraph.getVertexPtr(vert+START_VERTEX_NUM);
00428 vertexPtr->setTmp(count+1);
00429 (*theRefResult)(count) = vertexPtr->getRef();
00430 count++;
00431 }
00432 }
00433 }
00434 opserr << "Metis::number -3\n";
00435
00436 delete [] options;
00437 delete [] partition;
00438 delete [] xadj;
00439 delete [] adjncy;
00440 opserr << "Metis::number -4\n";
00441 return *theRefResult;
00442 }
00443
00444
00445 const ID &
00446 Metis::number(Graph &theGraph, const ID &lastVertices)
00447 {
00448 return this->number(theGraph);
00449 }
00450
00451 int
00452 Metis::sendSelf(int cTag, Channel &theChannel)
00453 {
00454 return 0;
00455 }
00456
00457 int
00458 Metis::recvSelf(int cTag, Channel &theChannel, FEM_ObjectBroker &theBroker)
00459 {
00460 return 0;
00461 }
00462