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
00041
00042
00043 #include "SundanceSerialPartitionerBase.hpp"
00044 #include "SundanceMap.hpp"
00045 #include "SundanceBasicSimplicialMeshType.hpp"
00046
00047 using namespace Sundance;
00048 using namespace Sundance;
00049
00050 using namespace Teuchos;
00051 using namespace Sundance;
00052
00053 using std::max;
00054 using std::min;
00055 using std::endl;
00056 using std::cout;
00057 using std::cerr;
00058
00059
00060
00061 Set<int> SerialPartitionerBase::arrayToSet(const Array<int>& a) const
00062 {
00063 Set<int> rtn;
00064 for (int i=0; i<a.size(); i++)
00065 {
00066 rtn.put(a[i]);
00067 }
00068 return rtn;
00069 }
00070
00071 int SerialPartitionerBase::max(const Set<int>& s) const
00072 {
00073 return *(s.rbegin());
00074 }
00075
00076 void SerialPartitionerBase::getNeighbors(const Mesh& mesh,
00077 Array<Array<int> >& neighbors, int& nEdges) const
00078 {
00079 int dim = mesh.spatialDim();
00080 int nElems = mesh.numCells(dim);
00081 int nVerts = mesh.numCells(0);
00082
00083 neighbors.resize(nElems);
00084 nEdges = 0;
00085
00086 elemVerts_.resize(nElems);
00087 elemEdgewiseNbors_.resize(nElems);
00088 vertElems_.resize(nVerts);
00089
00090
00091 for (int c=0; c<nElems; c++)
00092 {
00093 Array<int> facetLID;
00094 Array<int> facetDir;
00095
00096 mesh.getFacetArray(dim, c, 0, facetLID, facetDir);
00097 elemVerts_[c] = arrayToSet(facetLID);
00098
00099
00100 facetLID.resize(0);
00101 facetDir.resize(0);
00102 mesh.getFacetArray(dim, c, 1, facetLID, facetDir);
00103 Set<int> adjElems;
00104 for (int f=0; f<facetLID.size(); f++)
00105 {
00106 Array<int> maxCofs;
00107 mesh.getCofacets(1, facetLID[f], dim, maxCofs);
00108 for (int cf=0; cf<maxCofs.size(); cf++)
00109 {
00110 if (maxCofs[cf] != c) adjElems.put(maxCofs[cf]);
00111 }
00112 }
00113 elemEdgewiseNbors_[c] = adjElems;
00114 }
00115
00116 for (int v=0; v<nVerts; v++)
00117 {
00118 Array<int> cofacetLID;
00119 mesh.getCofacets(0, v, dim, cofacetLID);
00120 vertElems_[v] = arrayToSet(cofacetLID);
00121 }
00122
00123
00124 for (int i=0; i<nElems; i++)
00125 {
00126 Set<int> allNbors;
00127 const Set<int>& ev = elemVerts_[i];
00128 for (Set<int>::const_iterator v=ev.begin(); v!=ev.end(); v++)
00129 {
00130 allNbors = allNbors.setUnion(vertElems_[*v]);
00131 }
00132 allNbors.erase(i);
00133
00134 Array<int> fullNbors;
00135 for (Set<int>::const_iterator j=allNbors.begin(); j!=allNbors.end(); j++)
00136 {
00137 Set<int> numCommonNodes = elemVerts_[i].intersection(elemVerts_[*j]);
00138 if ((int) numCommonNodes.size() == dim) fullNbors.append(*j);
00139 }
00140 nEdges += fullNbors.size();
00141 neighbors[i] = fullNbors;
00142 }
00143
00144 nEdges = nEdges/2;
00145 }
00146
00147
00148 void SerialPartitionerBase::getNodeAssignments(int nProc,
00149 const Array<int>& elemAssignments,
00150 Array<int>& nodeAssignments,
00151 Array<int>& nodeOwnerElems,
00152 Array<int>& nodesPerProc) const
00153 {
00154 nodesPerProc.resize(nProc);
00155 nodeAssignments.resize(vertElems_.size());
00156 nodeOwnerElems.resize(vertElems_.size());
00157
00158 for (int i=0; i<nodesPerProc.size(); i++) nodesPerProc[i] = 0;
00159
00160 for (int v=0; v<vertElems_.size(); v++)
00161 {
00162
00163 int ownerElem = max(vertElems_[v]);
00164 nodeOwnerElems[v] = ownerElem;
00165 nodeAssignments[v] = elemAssignments[ownerElem];
00166 nodesPerProc[nodeAssignments[v]]++;
00167 }
00168 }
00169
00170 void SerialPartitionerBase::getElemsPerProc(int nProc,
00171 const Array<int>& elemAssignments,
00172 Array<int>& elemsPerProc) const
00173 {
00174 elemsPerProc.resize(nProc);
00175 for (int i=0; i<elemsPerProc.size(); i++) elemsPerProc[i] = 0;
00176
00177 for (int e=0; e<elemAssignments.size(); e++)
00178 {
00179 elemsPerProc[elemAssignments[e]]++;
00180 }
00181 }
00182
00183 void SerialPartitionerBase::remapEntities(const Array<int>& assignments,
00184 int nProc,
00185 Array<int>& entityMap) const
00186 {
00187 Array<Array<int> > procBuckets(nProc);
00188 entityMap.resize(assignments.size());
00189
00190 for (int i=0; i<assignments.size(); i++)
00191 {
00192 procBuckets[assignments[i]].append(i);
00193 }
00194
00195 int g = 0;
00196
00197 for (int p=0; p<nProc; p++)
00198 {
00199 for (int i=0; i<procBuckets[p].size(); i++)
00200 {
00201 int lid = procBuckets[p][i];
00202 entityMap[lid] = g++;
00203 }
00204 }
00205 }
00206
00207
00208 void SerialPartitionerBase::getOffProcData(int p,
00209 const Array<int>& elemAssignments,
00210 const Array<int>& nodeAssignments,
00211 Set<int>& offProcNodes,
00212 Set<int>& offProcElems) const
00213 {
00214 Out::root() << "ignore ghosts = " << ignoreGhosts_ << endl;
00215
00216 for (int e=0; e<elemAssignments.size(); e++)
00217 {
00218 if (elemAssignments[e] != p) continue;
00219 for (Set<int>::const_iterator v=elemVerts_[e].begin(); v!=elemVerts_[e].end(); v++)
00220 {
00221 if (nodeAssignments[*v]!=p) offProcNodes.put(*v);
00222 }
00223 if (!ignoreGhosts_)
00224 {
00225 for (Set<int>::const_iterator
00226 n=elemEdgewiseNbors_[e].begin(); n!=elemEdgewiseNbors_[e].end(); n++)
00227 {
00228 if (elemAssignments[*n]!=p) offProcElems.put(*n);
00229 }
00230 }
00231 }
00232
00233 if (!ignoreGhosts_)
00234 {
00235
00236 for (int v=0; v<nodeAssignments.size(); v++)
00237 {
00238 if (nodeAssignments[v] != p) continue;
00239 const Set<int>& v2e = vertElems_[v];
00240 for (Set<int>::const_iterator e=v2e.begin(); e!=v2e.end(); e++)
00241 {
00242 if (elemAssignments[*e] != p) offProcElems.put(*e);
00243 }
00244 }
00245
00246
00247
00248 for (Set<int>::const_iterator e=offProcElems.begin(); e!=offProcElems.end(); e++)
00249 {
00250 for (Set<int>::const_iterator v=elemVerts_[*e].begin(); v!=elemVerts_[*e].end(); v++)
00251 {
00252 if (nodeAssignments[*v]!=p) offProcNodes.put(*v);
00253 }
00254 }
00255 }
00256 }
00257
00258
00259 Array<Mesh> SerialPartitionerBase::makeMeshParts(const Mesh& mesh, int np,
00260 Array<Sundance::Map<int, int> >& oldElemLIDToNewLIDMaps,
00261 Array<Sundance::Map<int, int> >& oldVertLIDToNewLIDMaps) const
00262 {
00263 int dim = mesh.spatialDim();
00264
00265 Array<int> elemAssignments;
00266 Array<int> nodeAssignments;
00267 Array<int> nodeOwnerElems;
00268 Array<int> nodesPerProc;
00269
00270 getAssignments(mesh, np, elemAssignments);
00271
00272 getNodeAssignments(np, elemAssignments, nodeAssignments, nodeOwnerElems,
00273 nodesPerProc);
00274
00275 Array<Array<int> > offProcNodes(np);
00276 Array<Array<int> > offProcElems(np);
00277
00278 Array<Set<int> > offProcNodeSet(np);
00279 Array<Set<int> > offProcElemSet(np);
00280
00281 Array<Array<int> > procNodes(np);
00282 Array<Array<int> > procElems(np);
00283
00284 for (int p=0; p<np; p++)
00285 {
00286 getOffProcData(p, elemAssignments, nodeAssignments,
00287 offProcNodeSet[p], offProcElemSet[p]);
00288 offProcNodes[p] = offProcNodeSet[p].elements();
00289 offProcElems[p] = offProcElemSet[p].elements();
00290 procElems[p].reserve(elemAssignments.size()/np);
00291 procNodes[p].reserve(nodeAssignments.size()/np);
00292 }
00293
00294 Array<int> remappedElems;
00295 Array<int> remappedNodes;
00296
00297 remapEntities(elemAssignments, np, remappedElems);
00298 remapEntities(nodeAssignments, np, remappedNodes);
00299
00300 for (int e=0; e<elemAssignments.size(); e++)
00301 {
00302 procElems[elemAssignments[e]].append(e);
00303 }
00304
00305 for (int n=0; n<nodeAssignments.size(); n++)
00306 {
00307 procNodes[nodeAssignments[n]].append(n);
00308 }
00309
00310
00311 Array<Mesh> rtn(np);
00312 oldVertLIDToNewLIDMaps.resize(np);
00313 oldElemLIDToNewLIDMaps.resize(np);
00314 for (int p=0; p<np; p++)
00315 {
00316 Sundance::Map<int, int>& oldVertLIDToNewLIDMap
00317 = oldVertLIDToNewLIDMaps[p];
00318 Sundance::Map<int, int>& oldElemLIDToNewLIDMap
00319 = oldElemLIDToNewLIDMaps[p];
00320 MeshType type = new BasicSimplicialMeshType();
00321 rtn[p] = type.createEmptyMesh(mesh.spatialDim(), MPIComm::world());
00322
00323 Set<int> unusedVertGID;
00324
00325
00326 for (int n=0; n<procNodes[p].size(); n++)
00327 {
00328 int oldLID = procNodes[p][n];
00329 int newGID = remappedNodes[oldLID];
00330 unusedVertGID.put(newGID);
00331 int newLID = rtn[p].addVertex(newGID, mesh.nodePosition(oldLID), p, 0);
00332 oldVertLIDToNewLIDMap.put(oldLID, newLID);
00333 }
00334
00335
00336 for (int n=0; n<offProcNodes[p].size(); n++)
00337 {
00338 int oldLID = offProcNodes[p][n];
00339 int nodeOwnerProc = nodeAssignments[oldLID];
00340 int newGID = remappedNodes[oldLID];
00341 unusedVertGID.put(newGID);
00342 int newLID = rtn[p].addVertex(newGID, mesh.nodePosition(oldLID), nodeOwnerProc, 0);
00343 oldVertLIDToNewLIDMap.put(oldLID, newLID);
00344 }
00345
00346
00347 for (int e=0; e<procElems[p].size(); e++)
00348 {
00349 int oldLID = procElems[p][e];
00350 int newGID = remappedElems[oldLID];
00351 Array<int> vertGIDs;
00352 Array<int> orientations;
00353 mesh.getFacetArray(dim, oldLID, 0, vertGIDs, orientations);
00354 for (int v=0; v<vertGIDs.size(); v++)
00355 {
00356 vertGIDs[v] = remappedNodes[vertGIDs[v]];
00357 if (unusedVertGID.contains(vertGIDs[v])) unusedVertGID.erase(newGID);
00358 }
00359 int newLID = rtn[p].addElement(newGID, vertGIDs, p, 1);
00360 oldElemLIDToNewLIDMap.put(oldLID, newLID);
00361 }
00362
00363
00364 for (int e=0; e<offProcElems[p].size(); e++)
00365 {
00366 int oldLID = offProcElems[p][e];
00367 int newGID = remappedElems[oldLID];
00368 int elemOwnerProc = elemAssignments[oldLID];
00369 Array<int> vertGIDs;
00370 Array<int> orientations;
00371 mesh.getFacetArray(dim, oldLID, 0, vertGIDs, orientations);
00372 for (int v=0; v<vertGIDs.size(); v++)
00373 {
00374 vertGIDs[v] = remappedNodes[vertGIDs[v]];
00375 if (unusedVertGID.contains(vertGIDs[v])) unusedVertGID.erase(newGID);
00376 }
00377 int newLID = rtn[p].addElement(newGID, vertGIDs, elemOwnerProc, 1);
00378 oldElemLIDToNewLIDMap.put(oldLID, newLID);
00379
00380
00381
00382 }
00383
00384
00385
00386 for (int d=1; d<dim; d++)
00387 {
00388 Set<int> labels = mesh.getAllLabelsForDimension(d);
00389 for (Set<int>::const_iterator i=labels.begin(); i!=labels.end(); i++)
00390 {
00391 Array<int> labeledCells;
00392 int label = *i;
00393 if (label == 0) continue;
00394 mesh.getLIDsForLabel(d, label, labeledCells);
00395 for (int c=0; c<labeledCells.size(); c++)
00396 {
00397 int lid = labeledCells[c];
00398 Array<int> cofacets;
00399 mesh.getCofacets(d, lid, dim, cofacets);
00400 for (int n=0; n<cofacets.size(); n++)
00401 {
00402 int cofLID = cofacets[n];
00403 if (elemAssignments[cofLID]==p
00404 || offProcElemSet[p].contains(cofLID))
00405 {
00406
00407
00408
00409
00410 Array<int> oldVerts;
00411 Array<int> newVerts;
00412 Array<int> orientation;
00413 mesh.getFacetArray(d, lid, 0, oldVerts, orientation);
00414 for (int v=0; v<oldVerts.size(); v++)
00415 {
00416 newVerts.append(remappedNodes[oldVerts[v]]);
00417 }
00418
00419
00420 Set<int> newVertSet = arrayToSet(newVerts);
00421
00422
00423 int newElemLID = oldElemLIDToNewLIDMap.get(cofLID);
00424
00425
00426 Array<int> submeshFacets;
00427 rtn[p].getFacetArray(dim, newElemLID, d,
00428 submeshFacets, orientation);
00429 int facetIndex = -1;
00430 for (int df=0; df<submeshFacets.size(); df++)
00431 {
00432
00433 int facetLID = submeshFacets[df];
00434 Array<int> verts;
00435 rtn[p].getFacetArray(d, facetLID, 0, verts, orientation);
00436 Array<int> vertGID(verts.size());
00437 for (int v=0; v<verts.size(); v++)
00438 {
00439 vertGID[v] = rtn[p].mapLIDToGID(0, verts[v]);
00440 }
00441 Set<int> subVertSet = arrayToSet(vertGID);
00442 if (subVertSet==newVertSet)
00443 {
00444 facetIndex = df;
00445 break;
00446 }
00447 }
00448 TEUCHOS_TEST_FOR_EXCEPTION(facetIndex==-1, std::logic_error,
00449 "couldn't match new " << d << "-cell in submesh to old " << d
00450 << "cell. This should never happen");
00451
00452
00453
00454
00455 int o;
00456 int newFacetLID = rtn[p].facetLID(dim, newElemLID, d,
00457 facetIndex, o);
00458
00459 rtn[p].setLabel(d, newFacetLID, label);
00460 break;
00461
00462 }
00463 else
00464 {
00465 }
00466 }
00467 }
00468 }
00469 }
00470 }
00471
00472 return rtn;
00473 }
00474
00475