SundanceSerialPartitionerBase.cpp
Go to the documentation of this file.
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     /* assign the vertex to the highest-numbered cofacet */
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   /* first pass: find off-proc nodes required by on-proc elems */
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   /* second pass: find off-proc elems required by the on-proc nodes */
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   /* third pass: find the additional nodes required by the off-proc
00175    * elems found in the previous step */
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   /* Now we make NP submeshes */
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     /* add the on-processor nodes */
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     /* add the off-processor nodes */
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     /* add the on-processor elements */
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     /* add the off-processor elements */
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 //      TEST_FOR_EXCEPTION(unusedVertGID.size() != 0, InternalError,
00308 //        "unused vertices=" << unusedVertGID);
00309     }
00310 
00311     /* Now, propagate the labels of any intermediate-dimension cells
00312      * to the submesh */
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               /* at this point we need to find the facet index of the side
00334                * relative to the new element. */
00335               
00336               /* find vertices of old cell */
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               /* Put the vertices in a set. This will let us compare to the
00346                * vertex sets in the new submesh. */
00347               Set<int> newVertSet = arrayToSet(newVerts);
00348               
00349               /* Find the cofacet in the new submesh */
00350               int newElemLID = oldElemLIDToNewLIDMap.get(cofLID);
00351 
00352               /* Get the d-facets of the element in the new submesh */
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                 /* Get the vertices of this d-facet */
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               /* OK, now we have the d-cell's facet index relative to one
00380                * of its cofacets existing on the new submesh. We now
00381                * find the LID of the d-cell so we can set its label */
00382               int o;  // dummy orientation variable; not needed here
00383               int newFacetLID = rtn[p].facetLID(dim, newElemLID, d, 
00384                 facetIndex, o);
00385               /* Set the label, finally! */
00386               rtn[p].setLabel(d, newFacetLID, label);
00387               break; /* no need to continue the loop over cofacets once 
00388                       * we've set the label */
00389             }
00390             else
00391             {
00392             }
00393           }
00394         }
00395       }
00396     }
00397   }
00398 
00399   return rtn;
00400 }
00401 
00402 

Site Contact