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