OpenFOAM logo
The Open Source CFD Toolbox
  Source Guide OpenCFD Solutions Contact OpenFOAM

polyMeshAdder.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software; you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by the
00013     Free Software Foundation; either version 2 of the License, or (at your
00014     option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM; if not, write to the Free Software Foundation,
00023     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00024 
00025 \*----------------------------------------------------------------------------*/
00026 
00027 #include "polyMeshAdder.H"
00028 #include "mapAddedPolyMesh.H"
00029 #include "IOobject.H"
00030 #include "faceCoupleInfo.H"
00031 #include "processorPolyPatch.H"
00032 #include "SortableList.H"
00033 #include "Time.H"
00034 #include "globalMeshData.H"
00035 #include "mergePoints.H"
00036 #include "polyModifyFace.H"
00037 #include "polyRemovePoint.H"
00038 #include "polyTopoChange.H"
00039 
00040 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00041 
00042 //- Append all mapped elements of a list to a DynamicList
00043 void Foam::polyMeshAdder::append
00044 (
00045     const labelList& map,
00046     const labelList& lst,
00047     DynamicList<label>& dynLst
00048 )
00049 {
00050     dynLst.setCapacity(dynLst.size() + lst.size());
00051 
00052     forAll(lst, i)
00053     {
00054         label newElem = map[lst[i]];
00055 
00056         if (newElem != -1)
00057         {
00058             dynLst.append(newElem);
00059         }
00060     }
00061 }
00062 
00063 
00064 //- Append all mapped elements of a list to a DynamicList
00065 void Foam::polyMeshAdder::append
00066 (
00067     const labelList& map,
00068     const labelList& lst,
00069     const SortableList<label>& sortedLst,
00070     DynamicList<label>& dynLst
00071 )
00072 {
00073     dynLst.setSize(dynLst.size() + lst.size());
00074 
00075     forAll(lst, i)
00076     {
00077         label newElem = map[lst[i]];
00078 
00079         if (newElem != -1 && findSortedIndex(sortedLst, newElem) == -1)
00080         {
00081             dynLst.append(newElem);
00082         }
00083     }
00084 }
00085 
00086 
00087 // Get index of patch in new set of patchnames/types
00088 Foam::label Foam::polyMeshAdder::patchIndex
00089 (
00090     const polyPatch& p,
00091     DynamicList<word>& allPatchNames,
00092     DynamicList<word>& allPatchTypes
00093 )
00094 {
00095     // Find the patch name on the list.  If the patch is already there
00096     // and patch types match, return index
00097     const word& pType = p.type();
00098     const word& pName = p.name();
00099 
00100     label patchI = findIndex(allPatchNames, pName);
00101 
00102     if (patchI == -1)
00103     {
00104         // Patch not found. Append to the list
00105         allPatchNames.append(pName);
00106         allPatchTypes.append(pType);
00107 
00108         return allPatchNames.size() - 1;
00109     }
00110     else if (allPatchTypes[patchI] == pType)
00111     {
00112         // Found name and types match
00113         return patchI;
00114     }
00115     else
00116     {
00117         // Found the name, but type is different
00118 
00119         // Duplicate name is not allowed.  Create a composite name from the
00120         // patch name and case name
00121         const word& caseName = p.boundaryMesh().mesh().time().caseName();
00122 
00123         allPatchNames.append(pName + "_" + caseName);
00124         allPatchTypes.append(pType);
00125 
00126         Pout<< "label patchIndex(const polyPatch& p) : "
00127             << "Patch " << p.index() << " named "
00128             << pName << " in mesh " << caseName
00129             << " already exists, but patch types"
00130             << " do not match.\nCreating a composite name as "
00131             << allPatchNames[allPatchNames.size() - 1] << endl;
00132 
00133         return allPatchNames.size() - 1;
00134     }
00135 }
00136 
00137 
00138 // Get index of zone in new set of zone names
00139 Foam::label Foam::polyMeshAdder::zoneIndex
00140 (
00141     const word& curName,
00142     DynamicList<word>& names
00143 )
00144 {
00145     label zoneI = findIndex(names, curName);
00146 
00147     if (zoneI != -1)
00148     {
00149         return zoneI;
00150     }
00151     else
00152     {
00153         // Not found.  Add new name to the list
00154         names.append(curName);
00155 
00156         return names.size() - 1;
00157     }
00158 }
00159 
00160 
00161 void Foam::polyMeshAdder::mergePatchNames
00162 (
00163     const polyBoundaryMesh& patches0,
00164     const polyBoundaryMesh& patches1,
00165 
00166     DynamicList<word>& allPatchNames,
00167     DynamicList<word>& allPatchTypes,
00168 
00169     labelList& from1ToAllPatches,
00170     labelList& fromAllTo1Patches
00171 )
00172 {
00173     // Insert the mesh0 patches and zones
00174     append(patches0.names(), allPatchNames);
00175     append(patches0.types(), allPatchTypes);
00176 
00177 
00178     // Patches
00179     // ~~~~~~~
00180     // Patches from 0 are taken over as is; those from 1 get either merged
00181     // (if they share name and type) or appended.
00182     // Empty patches are filtered out much much later on.
00183 
00184     // Add mesh1 patches and build map both ways.
00185     from1ToAllPatches.setSize(patches1.size());
00186 
00187     forAll(patches1, patchI)
00188     {
00189         from1ToAllPatches[patchI] = patchIndex
00190         (
00191             patches1[patchI],
00192             allPatchNames,
00193             allPatchTypes
00194         );
00195     }
00196     allPatchTypes.shrink();
00197     allPatchNames.shrink();
00198 
00199     // Invert 1 to all patch map
00200     fromAllTo1Patches.setSize(allPatchNames.size());
00201     fromAllTo1Patches = -1;
00202 
00203     forAll(from1ToAllPatches, i)
00204     {
00205         fromAllTo1Patches[from1ToAllPatches[i]] = i;
00206     }
00207 }
00208 
00209 
00210 Foam::labelList Foam::polyMeshAdder::getPatchStarts
00211 (
00212     const polyBoundaryMesh& patches
00213 )
00214 {
00215     labelList patchStarts(patches.size());
00216     forAll(patches, patchI)
00217     {
00218         patchStarts[patchI] = patches[patchI].start();
00219     }
00220     return patchStarts;
00221 }
00222 
00223 
00224 Foam::labelList Foam::polyMeshAdder::getPatchSizes
00225 (
00226     const polyBoundaryMesh& patches
00227 )
00228 {
00229     labelList patchSizes(patches.size());
00230     forAll(patches, patchI)
00231     {
00232         patchSizes[patchI] = patches[patchI].size();
00233     }
00234     return patchSizes;
00235 }
00236 
00237 
00238 Foam::List<Foam::polyPatch*> Foam::polyMeshAdder::combinePatches
00239 (
00240     const polyMesh& mesh0,
00241     const polyMesh& mesh1,
00242     const polyBoundaryMesh& allBoundaryMesh,
00243     const label nAllPatches,
00244     const labelList& fromAllTo1Patches,
00245 
00246     const label nInternalFaces,
00247     const labelList& nFaces,
00248 
00249     labelList& from0ToAllPatches,
00250     labelList& from1ToAllPatches
00251 )
00252 {
00253     const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
00254     const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
00255 
00256 
00257     // Compacted new patch list.
00258     DynamicList<polyPatch*> allPatches(nAllPatches);
00259 
00260 
00261     // Map from 0 to all patches (since gets compacted)
00262     from0ToAllPatches.setSize(patches0.size());
00263     from0ToAllPatches = -1;
00264 
00265     label startFaceI = nInternalFaces;
00266 
00267     // Copy patches0 with new sizes. First patches always come from
00268     // mesh0 and will always be present.
00269     for (label patchI = 0; patchI < patches0.size(); patchI++)
00270     {
00271         // Originates from mesh0. Clone with new size & filter out empty
00272         // patch.
00273         label filteredPatchI;
00274 
00275         if (nFaces[patchI] == 0 && isA<processorPolyPatch>(patches0[patchI]))
00276         {
00277             //Pout<< "Removing zero sized mesh0 patch "
00278             //    << patches0[patchI].name() << endl;
00279             filteredPatchI = -1;
00280         }
00281         else
00282         {
00283             filteredPatchI = allPatches.size();
00284 
00285             allPatches.append
00286             (
00287                 patches0[patchI].clone
00288                 (
00289                     allBoundaryMesh,
00290                     filteredPatchI,
00291                     nFaces[patchI],
00292                     startFaceI
00293                 ).ptr()
00294             );
00295             startFaceI += nFaces[patchI];
00296         }
00297 
00298         // Record new index in allPatches
00299         from0ToAllPatches[patchI] = filteredPatchI;
00300 
00301         // Check if patch was also in mesh1 and update its addressing if so.
00302         if (fromAllTo1Patches[patchI] != -1)
00303         {
00304             from1ToAllPatches[fromAllTo1Patches[patchI]] = filteredPatchI;
00305         }
00306     }
00307 
00308     // Copy unique patches of mesh1.
00309     forAll(from1ToAllPatches, patchI)
00310     {
00311         label allPatchI = from1ToAllPatches[patchI];
00312 
00313         if (allPatchI >= patches0.size())
00314         {
00315             // Patch has not been merged with any mesh0 patch.
00316 
00317             label filteredPatchI;
00318 
00319             if
00320             (
00321                 nFaces[allPatchI] == 0
00322              && isA<processorPolyPatch>(patches1[patchI])
00323             )
00324             {
00325                 //Pout<< "Removing zero sized mesh1 patch "
00326                 //    << patches1[patchI].name() << endl;
00327                 filteredPatchI = -1;
00328             }
00329             else
00330             {
00331                 filteredPatchI = allPatches.size();
00332 
00333                 allPatches.append
00334                 (
00335                     patches1[patchI].clone
00336                     (
00337                         allBoundaryMesh,
00338                         filteredPatchI,
00339                         nFaces[allPatchI],
00340                         startFaceI
00341                     ).ptr()
00342                 );
00343                 startFaceI += nFaces[allPatchI];
00344             }
00345 
00346             from1ToAllPatches[patchI] = filteredPatchI;
00347         }
00348     }
00349 
00350     allPatches.shrink();
00351 
00352     return allPatches;
00353 }
00354 
00355 
00356 Foam::labelList Foam::polyMeshAdder::getFaceOrder
00357 (
00358     const cellList& cells,
00359     const label nInternalFaces,
00360     const labelList& owner,
00361     const labelList& neighbour
00362 )
00363 {
00364     labelList oldToNew(owner.size(), -1);
00365 
00366     // Leave boundary faces in order
00367     for (label faceI = nInternalFaces; faceI < owner.size(); faceI++)
00368     {
00369         oldToNew[faceI] = faceI;
00370     }
00371 
00372     // First unassigned face
00373     label newFaceI = 0;
00374 
00375     forAll(cells, cellI)
00376     {
00377         const labelList& cFaces = cells[cellI];
00378 
00379         SortableList<label> nbr(cFaces.size());
00380 
00381         forAll(cFaces, i)
00382         {
00383             label faceI = cFaces[i];
00384 
00385             label nbrCellI = neighbour[faceI];
00386 
00387             if (nbrCellI != -1)
00388             {
00389                 // Internal face. Get cell on other side.
00390                 if (nbrCellI == cellI)
00391                 {
00392                     nbrCellI = owner[faceI];
00393                 }
00394 
00395                 if (cellI < nbrCellI)
00396                 {
00397                     // CellI is master
00398                     nbr[i] = nbrCellI;
00399                 }
00400                 else
00401                 {
00402                     // nbrCell is master. Let it handle this face.
00403                     nbr[i] = -1;
00404                 }
00405             }
00406             else
00407             {
00408                 // External face. Do later.
00409                 nbr[i] = -1;
00410             }
00411         }
00412 
00413         nbr.sort();
00414 
00415         forAll(nbr, i)
00416         {
00417             if (nbr[i] != -1)
00418             {
00419                 oldToNew[cFaces[nbr.indices()[i]]] = newFaceI++;
00420             }
00421         }
00422     }
00423 
00424 
00425     // Check done all faces.
00426     forAll(oldToNew, faceI)
00427     {
00428         if (oldToNew[faceI] == -1)
00429         {
00430             FatalErrorIn
00431             (
00432                 "polyMeshAdder::getFaceOrder"
00433                 "(const cellList&, const label, const labelList&"
00434                 ", const labelList&) const"
00435             )   << "Did not determine new position"
00436                 << " for face " << faceI
00437                 << abort(FatalError);
00438         }
00439     }
00440 
00441     return oldToNew;
00442 }
00443 
00444 
00445 // Extends face f with split points. cutEdgeToPoints gives for every
00446 // edge the points introduced inbetween the endpoints.
00447 void Foam::polyMeshAdder::insertVertices
00448 (
00449     const edgeLookup& cutEdgeToPoints,
00450     const Map<label>& meshToMaster,
00451     const labelList& masterToCutPoints,
00452     const face& masterF,
00453 
00454     DynamicList<label>& workFace,
00455     face& allF
00456 )
00457 {
00458     workFace.clear();
00459 
00460     // Check any edge for being cut (check on the cut so takes account
00461     // for any point merging on the cut)
00462 
00463     forAll(masterF, fp)
00464     {
00465         label v0 = masterF[fp];
00466         label v1 = masterF.nextLabel(fp);
00467 
00468         // Copy existing face point
00469         workFace.append(allF[fp]);
00470 
00471         // See if any edge between v0,v1
00472 
00473         Map<label>::const_iterator v0Fnd = meshToMaster.find(v0);
00474         if (v0Fnd != meshToMaster.end())
00475         {
00476             Map<label>::const_iterator v1Fnd = meshToMaster.find(v1);
00477             if (v1Fnd != meshToMaster.end())
00478             {
00479                 // Get edge in cutPoint numbering
00480                 edge cutEdge
00481                 (
00482                     masterToCutPoints[v0Fnd()],
00483                     masterToCutPoints[v1Fnd()]
00484                 );
00485 
00486                 edgeLookup::const_iterator iter = cutEdgeToPoints.find(cutEdge);
00487 
00488                 if (iter != cutEdgeToPoints.end())
00489                 {
00490                     const edge& e = iter.key();
00491                     const labelList& addedPoints = iter();
00492 
00493                     // cutPoints first in allPoints so no need for renumbering
00494                     if (e[0] == cutEdge[0])
00495                     {
00496                         forAll(addedPoints, i)
00497                         {
00498                             workFace.append(addedPoints[i]);
00499                         }
00500                     }
00501                     else
00502                     {
00503                         forAllReverse(addedPoints, i)
00504                         {
00505                             workFace.append(addedPoints[i]);
00506                         }
00507                     }
00508                 }
00509             }
00510         }
00511     }
00512 
00513     if (workFace.size() != allF.size())
00514     {
00515         allF.transfer(workFace);
00516     }
00517 }
00518 
00519 
00520 // Adds primitives (cells, faces, points)
00521 // Cells:
00522 //  - all of mesh0
00523 //  - all of mesh1
00524 // Faces:
00525 //  - all uncoupled of mesh0
00526 //  - all coupled faces
00527 //  - all uncoupled of mesh1
00528 // Points:
00529 //  - all coupled
00530 //  - all uncoupled of mesh0
00531 //  - all uncoupled of mesh1
00532 void Foam::polyMeshAdder::mergePrimitives
00533 (
00534     const polyMesh& mesh0,
00535     const polyMesh& mesh1,
00536     const faceCoupleInfo& coupleInfo,
00537 
00538     const label nAllPatches,                // number of patches in the new mesh
00539     const labelList& fromAllTo1Patches,
00540     const labelList& from1ToAllPatches,
00541 
00542     pointField& allPoints,
00543     labelList& from0ToAllPoints,
00544     labelList& from1ToAllPoints,
00545 
00546     faceList& allFaces,
00547     labelList& allOwner,
00548     labelList& allNeighbour,
00549     label& nInternalFaces,
00550     labelList& nFacesPerPatch,
00551     label& nCells,
00552 
00553     labelList& from0ToAllFaces,
00554     labelList& from1ToAllFaces,
00555     labelList& from1ToAllCells
00556 )
00557 {
00558     const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
00559     const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
00560 
00561     const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
00562     const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
00563     const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
00564 
00565 
00566     // Points
00567     // ~~~~~~
00568 
00569     // Storage for new points
00570     allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
00571     label allPointI = 0;
00572 
00573     from0ToAllPoints.setSize(mesh0.nPoints());
00574     from0ToAllPoints = -1;
00575     from1ToAllPoints.setSize(mesh1.nPoints());
00576     from1ToAllPoints = -1;
00577 
00578     // Copy coupled points (on cut)
00579     {
00580         const pointField& cutPoints = coupleInfo.cutPoints();
00581 
00582         //const labelListList& cutToMasterPoints =
00583         //   coupleInfo.cutToMasterPoints();
00584         labelListList cutToMasterPoints
00585         (
00586             invertOneToMany
00587             (
00588                 cutPoints.size(),
00589                 coupleInfo.masterToCutPoints()
00590             )
00591         );
00592 
00593         //const labelListList& cutToSlavePoints =
00594         //    coupleInfo.cutToSlavePoints();
00595         labelListList cutToSlavePoints
00596         (
00597             invertOneToMany
00598             (
00599                 cutPoints.size(),
00600                 coupleInfo.slaveToCutPoints()
00601             )
00602         );
00603 
00604         forAll(cutPoints, i)
00605         {
00606             allPoints[allPointI] = cutPoints[i];
00607 
00608             // Mark all master and slave points referring to this point.
00609 
00610             const labelList& masterPoints = cutToMasterPoints[i];
00611 
00612             forAll(masterPoints, j)
00613             {
00614                 label mesh0PointI = masterPatch.meshPoints()[masterPoints[j]];
00615                 from0ToAllPoints[mesh0PointI] = allPointI;
00616             }
00617 
00618             const labelList& slavePoints = cutToSlavePoints[i];
00619 
00620             forAll(slavePoints, j)
00621             {
00622                 label mesh1PointI = slavePatch.meshPoints()[slavePoints[j]];
00623                 from1ToAllPoints[mesh1PointI] = allPointI;
00624             }
00625             allPointI++;
00626         }
00627     }
00628 
00629     // Add uncoupled mesh0 points
00630     forAll(mesh0.points(), pointI)
00631     {
00632         if (from0ToAllPoints[pointI] == -1)
00633         {
00634             allPoints[allPointI] = mesh0.points()[pointI];
00635             from0ToAllPoints[pointI] = allPointI;
00636             allPointI++;
00637         }
00638     }
00639 
00640     // Add uncoupled mesh1 points
00641     forAll(mesh1.points(), pointI)
00642     {
00643         if (from1ToAllPoints[pointI] == -1)
00644         {
00645             allPoints[allPointI] = mesh1.points()[pointI];
00646             from1ToAllPoints[pointI] = allPointI;
00647             allPointI++;
00648         }
00649     }
00650 
00651     allPoints.setSize(allPointI);
00652 
00653 
00654     // Faces
00655     // ~~~~~
00656 
00657     // Sizes per patch
00658     nFacesPerPatch.setSize(nAllPatches);
00659     nFacesPerPatch = 0;
00660 
00661     // Storage for faces and owner/neighbour
00662     allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
00663     allOwner.setSize(allFaces.size());
00664     allOwner = -1;
00665     allNeighbour.setSize(allFaces.size());
00666     allNeighbour = -1;
00667     label allFaceI = 0;
00668 
00669     from0ToAllFaces.setSize(mesh0.nFaces());
00670     from0ToAllFaces = -1;
00671     from1ToAllFaces.setSize(mesh1.nFaces());
00672     from1ToAllFaces = -1;
00673 
00674     // Copy mesh0 internal faces (always uncoupled)
00675     for (label faceI = 0; faceI < mesh0.nInternalFaces(); faceI++)
00676     {
00677         allFaces[allFaceI] = renumber(from0ToAllPoints, mesh0.faces()[faceI]);
00678         allOwner[allFaceI] = mesh0.faceOwner()[faceI];
00679         allNeighbour[allFaceI] = mesh0.faceNeighbour()[faceI];
00680         from0ToAllFaces[faceI] = allFaceI++;
00681     }
00682 
00683     // Copy coupled faces. Every coupled face has an equivalent master and
00684     // slave. Also uncount as boundary faces all the newly coupled faces.
00685     const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
00686     const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
00687 
00688     forAll(cutFaces, i)
00689     {
00690         label masterFaceI = cutToMasterFaces[i];
00691 
00692         label mesh0FaceI = masterPatch.addressing()[masterFaceI];
00693 
00694         if (from0ToAllFaces[mesh0FaceI] == -1)
00695         {
00696             // First occurrence of face
00697             from0ToAllFaces[mesh0FaceI] = allFaceI;
00698 
00699             // External face becomes internal so uncount
00700             label patch0 = patches0.whichPatch(mesh0FaceI);
00701             nFacesPerPatch[patch0]--;
00702         }
00703 
00704         label slaveFaceI = cutToSlaveFaces[i];
00705 
00706         label mesh1FaceI = slavePatch.addressing()[slaveFaceI];
00707 
00708         if (from1ToAllFaces[mesh1FaceI] == -1)
00709         {
00710             from1ToAllFaces[mesh1FaceI] = allFaceI;
00711 
00712             label patch1 = patches1.whichPatch(mesh1FaceI);
00713             nFacesPerPatch[from1ToAllPatches[patch1]]--;
00714         }
00715 
00716         // Copy cut face (since cutPoints are copied first no renumbering
00717         // nessecary)
00718         allFaces[allFaceI] = cutFaces[i];
00719         allOwner[allFaceI] = mesh0.faceOwner()[mesh0FaceI];
00720         allNeighbour[allFaceI] = mesh1.faceOwner()[mesh1FaceI] + mesh0.nCells();
00721 
00722         allFaceI++;
00723     }
00724 
00725     // Copy mesh1 internal faces (always uncoupled)
00726     for (label faceI = 0; faceI < mesh1.nInternalFaces(); faceI++)
00727     {
00728         allFaces[allFaceI] = renumber(from1ToAllPoints, mesh1.faces()[faceI]);
00729         allOwner[allFaceI] = mesh1.faceOwner()[faceI] + mesh0.nCells();
00730         allNeighbour[allFaceI] = mesh1.faceNeighbour()[faceI] + mesh0.nCells();
00731         from1ToAllFaces[faceI] = allFaceI++;
00732     }
00733 
00734     nInternalFaces = allFaceI;
00735 
00736     // Copy (unmarked/uncoupled) external faces in new order.
00737     for (label allPatchI = 0; allPatchI < nAllPatches; allPatchI++)
00738     {
00739         if (allPatchI < patches0.size())
00740         {
00741             // Patch is present in mesh0
00742             const polyPatch& pp = patches0[allPatchI];
00743 
00744             nFacesPerPatch[allPatchI] += pp.size();
00745 
00746             label faceI = pp.start();
00747 
00748             forAll(pp, i)
00749             {
00750                 if (from0ToAllFaces[faceI] == -1)
00751                 {
00752                     // Is uncoupled face since has not yet been dealt with
00753                     allFaces[allFaceI] = renumber
00754                     (
00755                         from0ToAllPoints,
00756                         mesh0.faces()[faceI]
00757                     );
00758                     allOwner[allFaceI] = mesh0.faceOwner()[faceI];
00759                     allNeighbour[allFaceI] = -1;
00760 
00761                     from0ToAllFaces[faceI] = allFaceI++;
00762                 }
00763                 faceI++;
00764             }
00765         }
00766         if (fromAllTo1Patches[allPatchI] != -1)
00767         {
00768             // Patch is present in mesh1
00769             const polyPatch& pp = patches1[fromAllTo1Patches[allPatchI]];
00770 
00771             nFacesPerPatch[allPatchI] += pp.size();
00772 
00773             label faceI = pp.start();
00774 
00775             forAll(pp, i)
00776             {
00777                 if (from1ToAllFaces[faceI] == -1)
00778                 {
00779                     // Is uncoupled face
00780                     allFaces[allFaceI] = renumber
00781                     (
00782                         from1ToAllPoints,
00783                         mesh1.faces()[faceI]
00784                     );
00785                     allOwner[allFaceI] =
00786                         mesh1.faceOwner()[faceI]
00787                       + mesh0.nCells();
00788                     allNeighbour[allFaceI] = -1;
00789 
00790                     from1ToAllFaces[faceI] = allFaceI++;
00791                 }
00792                 faceI++;
00793             }
00794         }
00795     }
00796     allFaces.setSize(allFaceI);
00797     allOwner.setSize(allFaceI);
00798     allNeighbour.setSize(allFaceI);
00799 
00800 
00801     // So now we have all ok for one-to-one mapping.
00802     // For split slace faces:
00803     // - mesh consistent with slave side
00804     // - mesh not consistent with owner side. It is not zipped up, the
00805     //   original faces need edges split.
00806 
00807     // Use brute force to prevent having to calculate addressing:
00808     // - get map from master edge to split edges.
00809     // - check all faces to find any edge that is split.
00810     {
00811         // From two cut-points to labels of cut-points inbetween.
00812         // (in order: from e[0] to e[1]
00813         const edgeLookup& cutEdgeToPoints = coupleInfo.cutEdgeToPoints();
00814 
00815         // Get map of master face (in mesh labels) that are in cut. These faces
00816         // do not need to be renumbered.
00817         labelHashSet masterCutFaces(cutToMasterFaces.size());
00818         forAll(cutToMasterFaces, i)
00819         {
00820             label meshFaceI = masterPatch.addressing()[cutToMasterFaces[i]];
00821 
00822             masterCutFaces.insert(meshFaceI);
00823         }
00824 
00825         DynamicList<label> workFace(100);
00826 
00827         forAll(from0ToAllFaces, face0)
00828         {
00829             if (!masterCutFaces.found(face0))
00830             {
00831                 label allFaceI = from0ToAllFaces[face0];
00832 
00833                 insertVertices
00834                 (
00835                     cutEdgeToPoints,
00836                     masterPatch.meshPointMap(),
00837                     coupleInfo.masterToCutPoints(),
00838                     mesh0.faces()[face0],
00839 
00840                     workFace,
00841                     allFaces[allFaceI]
00842                 );
00843             }
00844         }
00845 
00846         // Same for slave face
00847 
00848         labelHashSet slaveCutFaces(cutToSlaveFaces.size());
00849         forAll(cutToSlaveFaces, i)
00850         {
00851             label meshFaceI = slavePatch.addressing()[cutToSlaveFaces[i]];
00852 
00853             slaveCutFaces.insert(meshFaceI);
00854         }
00855 
00856         forAll(from1ToAllFaces, face1)
00857         {
00858             if (!slaveCutFaces.found(face1))
00859             {
00860                 label allFaceI = from1ToAllFaces[face1];
00861 
00862                 insertVertices
00863                 (
00864                     cutEdgeToPoints,
00865                     slavePatch.meshPointMap(),
00866                     coupleInfo.slaveToCutPoints(),
00867                     mesh1.faces()[face1],
00868 
00869                     workFace,
00870                     allFaces[allFaceI]
00871                 );
00872             }
00873         }
00874     }
00875 
00876     // Now we have a full facelist and owner/neighbour addressing.
00877 
00878 
00879     // Cells
00880     // ~~~~~
00881 
00882     from1ToAllCells.setSize(mesh1.nCells());
00883     from1ToAllCells = -1;
00884 
00885     forAll(mesh1.cells(), i)
00886     {
00887         from1ToAllCells[i] = i + mesh0.nCells();
00888     }
00889 
00890     // Make cells (= cell-face addressing)
00891     nCells = mesh0.nCells() + mesh1.nCells();
00892     cellList allCells(nCells);
00893     primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
00894 
00895     // Reorder faces for upper-triangular order.
00896     labelList oldToNew
00897     (
00898         getFaceOrder
00899         (
00900             allCells,
00901             nInternalFaces,
00902             allOwner,
00903             allNeighbour
00904         )
00905     );
00906 
00907     inplaceReorder(oldToNew, allFaces);
00908     inplaceReorder(oldToNew, allOwner);
00909     inplaceReorder(oldToNew, allNeighbour);
00910     inplaceRenumber(oldToNew, from0ToAllFaces);
00911     inplaceRenumber(oldToNew, from1ToAllFaces);
00912 }
00913 
00914 
00915 void Foam::polyMeshAdder::mergePointZones
00916 (
00917     const pointZoneMesh& pz0,
00918     const pointZoneMesh& pz1,
00919     const labelList& from0ToAllPoints,
00920     const labelList& from1ToAllPoints,
00921 
00922     DynamicList<word>& zoneNames,
00923     labelList& from1ToAll,
00924     List<DynamicList<label> >& pzPoints
00925 )
00926 {
00927     zoneNames.setCapacity(pz0.size() + pz1.size());
00928 
00929     // Names
00930     append(pz0.names(), zoneNames);
00931 
00932     from1ToAll.setSize(pz1.size());
00933 
00934     forAll (pz1, zoneI)
00935     {
00936         from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
00937     }
00938     zoneNames.shrink();
00939 
00940     // Point labels per merged zone
00941     pzPoints.setSize(zoneNames.size());
00942 
00943     forAll(pz0, zoneI)
00944     {
00945         append(from0ToAllPoints, pz0[zoneI], pzPoints[zoneI]);
00946     }
00947 
00948     // Get sorted zone contents for duplicate element recognition
00949     PtrList<SortableList<label> > pzPointsSorted(pzPoints.size());
00950     forAll(pzPoints, zoneI)
00951     {
00952         pzPointsSorted.set
00953         (
00954             zoneI,
00955             new SortableList<label>(pzPoints[zoneI])
00956         );
00957     }
00958 
00959     // Now we have full addressing for points so do the pointZones of mesh1.
00960     forAll(pz1, zoneI)
00961     {
00962         // Relabel all points of zone and add to correct pzPoints.
00963         label allZoneI = from1ToAll[zoneI];
00964 
00965         append
00966         (
00967             from1ToAllPoints,
00968             pz1[zoneI],
00969             pzPointsSorted[allZoneI],
00970             pzPoints[allZoneI]
00971         );
00972     }
00973 
00974     forAll(pzPoints, i)
00975     {
00976         pzPoints[i].shrink();
00977     }
00978 }
00979 
00980 
00981 void Foam::polyMeshAdder::mergeFaceZones
00982 (
00983     const faceZoneMesh& fz0,
00984     const faceZoneMesh& fz1,
00985     const labelList& from0ToAllFaces,
00986     const labelList& from1ToAllFaces,
00987 
00988     DynamicList<word>& zoneNames,
00989     labelList& from1ToAll,
00990     List<DynamicList<label> >& fzFaces,
00991     List<DynamicList<bool> >& fzFlips
00992 )
00993 {
00994     zoneNames.setCapacity(fz0.size() + fz1.size());
00995 
00996     append(fz0.names(), zoneNames);
00997 
00998     from1ToAll.setSize(fz1.size());
00999 
01000     forAll (fz1, zoneI)
01001     {
01002         from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
01003     }
01004     zoneNames.shrink();
01005 
01006 
01007     // Create temporary lists for faceZones.
01008     fzFaces.setSize(zoneNames.size());
01009     fzFlips.setSize(zoneNames.size());
01010     forAll(fz0, zoneI)
01011     {
01012         DynamicList<label>& newZone = fzFaces[zoneI];
01013         DynamicList<bool>& newFlip = fzFlips[zoneI];
01014 
01015         newZone.setCapacity(fz0[zoneI].size());
01016         newFlip.setCapacity(newZone.size());
01017 
01018         const labelList& addressing = fz0[zoneI];
01019         const boolList& flipMap = fz0[zoneI].flipMap();
01020 
01021         forAll(addressing, i)
01022         {
01023             label faceI = addressing[i];
01024 
01025             if (from0ToAllFaces[faceI] != -1)
01026             {
01027                 newZone.append(from0ToAllFaces[faceI]);
01028                 newFlip.append(flipMap[i]);
01029             }
01030         }
01031     }
01032 
01033     // Get sorted zone contents for duplicate element recognition
01034     PtrList<SortableList<label> > fzFacesSorted(fzFaces.size());
01035     forAll(fzFaces, zoneI)
01036     {
01037         fzFacesSorted.set
01038         (
01039             zoneI,
01040             new SortableList<label>(fzFaces[zoneI])
01041         );
01042     }
01043 
01044     // Now we have full addressing for faces so do the faceZones of mesh1.
01045     forAll(fz1, zoneI)
01046     {
01047         label allZoneI = from1ToAll[zoneI];
01048 
01049         DynamicList<label>& newZone = fzFaces[allZoneI];
01050         const SortableList<label>& newZoneSorted = fzFacesSorted[allZoneI];
01051         DynamicList<bool>& newFlip = fzFlips[allZoneI];
01052 
01053         newZone.setCapacity(newZone.size() + fz1[zoneI].size());
01054         newFlip.setCapacity(newZone.size());
01055 
01056         const labelList& addressing = fz1[zoneI];
01057         const boolList& flipMap = fz1[zoneI].flipMap();
01058 
01059         forAll(addressing, i)
01060         {
01061             label faceI = addressing[i];
01062             label allFaceI = from1ToAllFaces[faceI];
01063 
01064             if
01065             (
01066                 allFaceI != -1
01067              && findSortedIndex(newZoneSorted, allFaceI) == -1
01068             )
01069             {
01070                 newZone.append(allFaceI);
01071                 newFlip.append(flipMap[i]);
01072             }
01073         }
01074     }
01075 
01076     forAll(fzFaces, i)
01077     {
01078         fzFaces[i].shrink();
01079         fzFlips[i].shrink();
01080     }
01081 }
01082 
01083 
01084 void Foam::polyMeshAdder::mergeCellZones
01085 (
01086     const cellZoneMesh& cz0,
01087     const cellZoneMesh& cz1,
01088     const labelList& from1ToAllCells,
01089 
01090     DynamicList<word>& zoneNames,
01091     labelList& from1ToAll,
01092     List<DynamicList<label> >& czCells
01093 )
01094 {
01095     zoneNames.setCapacity(cz0.size() + cz1.size());
01096 
01097     append(cz0.names(), zoneNames);
01098 
01099     from1ToAll.setSize(cz1.size());
01100     forAll (cz1, zoneI)
01101     {
01102         from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
01103     }
01104     zoneNames.shrink();
01105 
01106 
01107     // Create temporary lists for cellZones.
01108     czCells.setSize(zoneNames.size());
01109     forAll(cz0, zoneI)
01110     {
01111         // Insert mesh0 cells
01112         append(cz0[zoneI], czCells[zoneI]);
01113     }
01114 
01115 
01116     // Cell mapping is trivial.
01117     forAll(cz1, zoneI)
01118     {
01119         label allZoneI = from1ToAll[zoneI];
01120 
01121         append(from1ToAllCells, cz1[zoneI], czCells[allZoneI]);
01122     }
01123 
01124     forAll(czCells, i)
01125     {
01126         czCells[i].shrink();
01127     }
01128 }
01129 
01130 
01131 void Foam::polyMeshAdder::mergeZones
01132 (
01133     const polyMesh& mesh0,
01134     const polyMesh& mesh1,
01135     const labelList& from0ToAllPoints,
01136     const labelList& from0ToAllFaces,
01137 
01138     const labelList& from1ToAllPoints,
01139     const labelList& from1ToAllFaces,
01140     const labelList& from1ToAllCells,
01141 
01142     DynamicList<word>& pointZoneNames,
01143     List<DynamicList<label> >& pzPoints,
01144 
01145     DynamicList<word>& faceZoneNames,
01146     List<DynamicList<label> >& fzFaces,
01147     List<DynamicList<bool> >& fzFlips,
01148 
01149     DynamicList<word>& cellZoneNames,
01150     List<DynamicList<label> >& czCells
01151 )
01152 {
01153     labelList from1ToAllPZones;
01154     mergePointZones
01155     (
01156         mesh0.pointZones(),
01157         mesh1.pointZones(),
01158         from0ToAllPoints,
01159         from1ToAllPoints,
01160 
01161         pointZoneNames,
01162         from1ToAllPZones,
01163         pzPoints
01164     );
01165 
01166     labelList from1ToAllFZones;
01167     mergeFaceZones
01168     (
01169         mesh0.faceZones(),
01170         mesh1.faceZones(),
01171         from0ToAllFaces,
01172         from1ToAllFaces,
01173 
01174         faceZoneNames,
01175         from1ToAllFZones,
01176         fzFaces,
01177         fzFlips
01178     );
01179 
01180     labelList from1ToAllCZones;
01181     mergeCellZones
01182     (
01183         mesh0.cellZones(),
01184         mesh1.cellZones(),
01185         from1ToAllCells,
01186 
01187         cellZoneNames,
01188         from1ToAllCZones,
01189         czCells
01190     );
01191 }
01192 
01193 
01194 void Foam::polyMeshAdder::addZones
01195 (
01196     const DynamicList<word>& pointZoneNames,
01197     const List<DynamicList<label> >& pzPoints,
01198 
01199     const DynamicList<word>& faceZoneNames,
01200     const List<DynamicList<label> >& fzFaces,
01201     const List<DynamicList<bool> >& fzFlips,
01202 
01203     const DynamicList<word>& cellZoneNames,
01204     const List<DynamicList<label> >& czCells,
01205 
01206     polyMesh& mesh
01207 )
01208 {
01209     List<pointZone*> pZones(pzPoints.size());
01210     forAll(pZones, i)
01211     {
01212         pZones[i] = new pointZone
01213         (
01214             pointZoneNames[i],
01215             pzPoints[i],
01216             i,
01217             mesh.pointZones()
01218         );
01219     }
01220 
01221     List<faceZone*> fZones(fzFaces.size());
01222     forAll(fZones, i)
01223     {
01224         fZones[i] = new faceZone
01225         (
01226             faceZoneNames[i],
01227             fzFaces[i],
01228             fzFlips[i],
01229             i,
01230             mesh.faceZones()
01231         );
01232     }
01233 
01234     List<cellZone*> cZones(czCells.size());
01235     forAll(cZones, i)
01236     {
01237         cZones[i] = new cellZone
01238         (
01239             cellZoneNames[i],
01240             czCells[i],
01241             i,
01242             mesh.cellZones()
01243         );
01244     }
01245 
01246     mesh.addZones
01247     (
01248         pZones,
01249         fZones,
01250         cZones
01251     );
01252 }
01253 
01254 
01255 
01256 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
01257 
01258 // Returns new mesh and sets
01259 // - map from new cell/face/point/patch to either mesh0 or mesh1
01260 //
01261 // mesh0Faces/mesh1Faces: corresponding faces on both meshes.
01262 Foam::autoPtr<Foam::polyMesh> Foam::polyMeshAdder::add
01263 (
01264     const IOobject& io,
01265     const polyMesh& mesh0,
01266     const polyMesh& mesh1,
01267     const faceCoupleInfo& coupleInfo,
01268     autoPtr<mapAddedPolyMesh>& mapPtr
01269 )
01270 {
01271     const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
01272     const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
01273 
01274 
01275     DynamicList<word> allPatchNames(patches0.size() + patches1.size());
01276     DynamicList<word> allPatchTypes(allPatchNames.size());
01277 
01278     // Patch maps
01279     labelList from1ToAllPatches(patches1.size());
01280     labelList fromAllTo1Patches(allPatchNames.size(), -1);
01281 
01282     mergePatchNames
01283     (
01284         patches0,
01285         patches1,
01286         allPatchNames,
01287         allPatchTypes,
01288         from1ToAllPatches,
01289         fromAllTo1Patches
01290     );
01291 
01292 
01293     // New points
01294     pointField allPoints;
01295 
01296     // Map from mesh0/1 points to allPoints.
01297     labelList from0ToAllPoints(mesh0.nPoints(), -1);
01298     labelList from1ToAllPoints(mesh1.nPoints(), -1);
01299 
01300     // New faces
01301     faceList allFaces;
01302     label nInternalFaces;
01303 
01304     // New cells
01305     labelList allOwner;
01306     labelList allNeighbour;
01307     label nCells;
01308 
01309     // Sizes per patch
01310     labelList nFaces(allPatchNames.size(), 0);
01311 
01312     // Maps
01313     labelList from0ToAllFaces(mesh0.nFaces(), -1);
01314     labelList from1ToAllFaces(mesh1.nFaces(), -1);
01315 
01316     // Map
01317     labelList from1ToAllCells(mesh1.nCells(), -1);
01318 
01319     mergePrimitives
01320     (
01321         mesh0,
01322         mesh1,
01323         coupleInfo,
01324 
01325         allPatchNames.size(),
01326         fromAllTo1Patches,
01327         from1ToAllPatches,
01328 
01329         allPoints,
01330         from0ToAllPoints,
01331         from1ToAllPoints,
01332 
01333         allFaces,
01334         allOwner,
01335         allNeighbour,
01336         nInternalFaces,
01337         nFaces,
01338         nCells,
01339 
01340         from0ToAllFaces,
01341         from1ToAllFaces,
01342         from1ToAllCells
01343     );
01344 
01345 
01346     // Zones
01347     // ~~~~~
01348 
01349     DynamicList<word> pointZoneNames;
01350     List<DynamicList<label> > pzPoints;
01351 
01352     DynamicList<word> faceZoneNames;
01353     List<DynamicList<label> > fzFaces;
01354     List<DynamicList<bool> > fzFlips;
01355 
01356     DynamicList<word> cellZoneNames;
01357     List<DynamicList<label> > czCells;
01358 
01359     mergeZones
01360     (
01361         mesh0,
01362         mesh1,
01363 
01364         from0ToAllPoints,
01365         from0ToAllFaces,
01366 
01367         from1ToAllPoints,
01368         from1ToAllFaces,
01369         from1ToAllCells,
01370 
01371         pointZoneNames,
01372         pzPoints,
01373 
01374         faceZoneNames,
01375         fzFaces,
01376         fzFlips,
01377 
01378         cellZoneNames,
01379         czCells
01380     );
01381 
01382 
01383     // Patches
01384     // ~~~~~~~
01385 
01386     // Map from 0 to all patches (since gets compacted)
01387     labelList from0ToAllPatches(patches0.size(), -1);
01388 
01389     List<polyPatch*> allPatches
01390     (
01391         combinePatches
01392         (
01393             mesh0,
01394             mesh1,
01395             patches0,           // Should be boundaryMesh() on new mesh.
01396             allPatchNames.size(),
01397             fromAllTo1Patches,
01398             mesh0.nInternalFaces()
01399           + mesh1.nInternalFaces()
01400           + coupleInfo.cutFaces().size(),
01401             nFaces,
01402 
01403             from0ToAllPatches,
01404             from1ToAllPatches
01405         )
01406     );
01407 
01408 
01409     // Map information
01410     // ~~~~~~~~~~~~~~~
01411 
01412     mapPtr.reset
01413     (
01414         new mapAddedPolyMesh
01415         (
01416             mesh0.nPoints(),
01417             mesh0.nFaces(),
01418             mesh0.nCells(),
01419 
01420             mesh1.nPoints(),
01421             mesh1.nFaces(),
01422             mesh1.nCells(),
01423 
01424             from0ToAllPoints,
01425             from0ToAllFaces,
01426             identity(mesh0.nCells()),
01427 
01428             from1ToAllPoints,
01429             from1ToAllFaces,
01430             from1ToAllCells,
01431 
01432             from0ToAllPatches,
01433             from1ToAllPatches,
01434             getPatchSizes(patches0),
01435             getPatchStarts(patches0)
01436         )
01437     );
01438 
01439 
01440 
01441     // Now we have extracted all information from all meshes.
01442     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01443 
01444     // Construct mesh
01445     autoPtr<polyMesh> tmesh
01446     (
01447         new polyMesh
01448         (
01449             io,
01450             xferMove(allPoints),
01451             xferMove(allFaces),
01452             xferMove(allOwner),
01453             xferMove(allNeighbour)
01454         )
01455     );
01456     polyMesh& mesh = tmesh();
01457 
01458     // Add zones to new mesh.
01459     addZones
01460     (
01461         pointZoneNames,
01462         pzPoints,
01463 
01464         faceZoneNames,
01465         fzFaces,
01466         fzFlips,
01467 
01468         cellZoneNames,
01469         czCells,
01470         mesh
01471     );
01472 
01473     // Add patches to new mesh
01474     mesh.addPatches(allPatches);
01475 
01476     return tmesh;
01477 }
01478 
01479 
01480 // Inplace add mesh1 to mesh0
01481 Foam::autoPtr<Foam::mapAddedPolyMesh> Foam::polyMeshAdder::add
01482 (
01483     polyMesh& mesh0,
01484     const polyMesh& mesh1,
01485     const faceCoupleInfo& coupleInfo,
01486     const bool validBoundary
01487 )
01488 {
01489     const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
01490     const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
01491 
01492     DynamicList<word> allPatchNames(patches0.size() + patches1.size());
01493     DynamicList<word> allPatchTypes(allPatchNames.size());
01494 
01495     // Patch maps
01496     labelList from1ToAllPatches(patches1.size());
01497     labelList fromAllTo1Patches(allPatchNames.size(), -1);
01498 
01499     mergePatchNames
01500     (
01501         patches0,
01502         patches1,
01503         allPatchNames,
01504         allPatchTypes,
01505         from1ToAllPatches,
01506         fromAllTo1Patches
01507     );
01508 
01509 
01510     // New points
01511     pointField allPoints;
01512 
01513     // Map from mesh0/1 points to allPoints.
01514     labelList from0ToAllPoints(mesh0.nPoints(), -1);
01515     labelList from1ToAllPoints(mesh1.nPoints(), -1);
01516 
01517     // New faces
01518     faceList allFaces;
01519     labelList allOwner;
01520     labelList allNeighbour;
01521     label nInternalFaces;
01522     // Sizes per patch
01523     labelList nFaces(allPatchNames.size(), 0);
01524     label nCells;
01525 
01526     // Maps
01527     labelList from0ToAllFaces(mesh0.nFaces(), -1);
01528     labelList from1ToAllFaces(mesh1.nFaces(), -1);
01529     // Map
01530     labelList from1ToAllCells(mesh1.nCells(), -1);
01531 
01532     mergePrimitives
01533     (
01534         mesh0,
01535         mesh1,
01536         coupleInfo,
01537 
01538         allPatchNames.size(),
01539         fromAllTo1Patches,
01540         from1ToAllPatches,
01541 
01542         allPoints,
01543         from0ToAllPoints,
01544         from1ToAllPoints,
01545 
01546         allFaces,
01547         allOwner,
01548         allNeighbour,
01549         nInternalFaces,
01550         nFaces,
01551         nCells,
01552 
01553         from0ToAllFaces,
01554         from1ToAllFaces,
01555         from1ToAllCells
01556     );
01557 
01558 
01559     // Zones
01560     // ~~~~~
01561 
01562     DynamicList<word> pointZoneNames;
01563     List<DynamicList<label> > pzPoints;
01564 
01565     DynamicList<word> faceZoneNames;
01566     List<DynamicList<label> > fzFaces;
01567     List<DynamicList<bool> > fzFlips;
01568 
01569     DynamicList<word> cellZoneNames;
01570     List<DynamicList<label> > czCells;
01571 
01572     mergeZones
01573     (
01574         mesh0,
01575         mesh1,
01576 
01577         from0ToAllPoints,
01578         from0ToAllFaces,
01579 
01580         from1ToAllPoints,
01581         from1ToAllFaces,
01582         from1ToAllCells,
01583 
01584         pointZoneNames,
01585         pzPoints,
01586 
01587         faceZoneNames,
01588         fzFaces,
01589         fzFlips,
01590 
01591         cellZoneNames,
01592         czCells
01593     );
01594 
01595 
01596     // Patches
01597     // ~~~~~~~
01598 
01599 
01600     // Store mesh0 patch info before modifying patches0.
01601     labelList mesh0PatchSizes(getPatchSizes(patches0));
01602     labelList mesh0PatchStarts(getPatchStarts(patches0));
01603 
01604     // Map from 0 to all patches (since gets compacted)
01605     labelList from0ToAllPatches(patches0.size(), -1);
01606 
01607     // Inplace extend mesh0 patches (note that patches0.size() now also
01608     // has changed)
01609     polyBoundaryMesh& allPatches =
01610         const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
01611     allPatches.setSize(allPatchNames.size());
01612 
01613     label startFaceI = nInternalFaces;
01614 
01615     // Copy patches0 with new sizes. First patches always come from
01616     // mesh0 and will always be present.
01617     label allPatchI = 0;
01618 
01619     forAll(from0ToAllPatches, patch0)
01620     {
01621         // Originates from mesh0. Clone with new size & filter out empty
01622         // patch.
01623 
01624         if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
01625         {
01626             //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
01627             //    << endl;
01628             from0ToAllPatches[patch0] = -1;
01629             // Check if patch was also in mesh1 and update its addressing if so.
01630             if (fromAllTo1Patches[patch0] != -1)
01631             {
01632                 from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
01633             }
01634         }
01635         else
01636         {
01637             // Clone.
01638             allPatches.set
01639             (
01640                 allPatchI,
01641                 allPatches[patch0].clone
01642                 (
01643                     allPatches,
01644                     allPatchI,
01645                     nFaces[patch0],
01646                     startFaceI
01647                 )
01648             );
01649 
01650             // Record new index in allPatches
01651             from0ToAllPatches[patch0] = allPatchI;
01652 
01653             // Check if patch was also in mesh1 and update its addressing if so.
01654             if (fromAllTo1Patches[patch0] != -1)
01655             {
01656                 from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchI;
01657             }
01658 
01659             startFaceI += nFaces[patch0];
01660 
01661             allPatchI++;
01662         }
01663     }
01664 
01665     // Copy unique patches of mesh1.
01666     forAll(from1ToAllPatches, patch1)
01667     {
01668         label uncompactAllPatchI = from1ToAllPatches[patch1];
01669 
01670         if (uncompactAllPatchI >= from0ToAllPatches.size())
01671         {
01672             // Patch has not been merged with any mesh0 patch.
01673 
01674             if
01675             (
01676                 nFaces[uncompactAllPatchI] == 0
01677              && isA<processorPolyPatch>(patches1[patch1])
01678             )
01679             {
01680                 //Pout<< "Removing zero sized mesh1 patch "
01681                 //    << allPatchNames[uncompactAllPatchI] << endl;
01682                 from1ToAllPatches[patch1] = -1;
01683             }
01684             else
01685             {
01686                 // Clone.
01687                 allPatches.set
01688                 (
01689                     allPatchI,
01690                     patches1[patch1].clone
01691                     (
01692                         allPatches,
01693                         allPatchI,
01694                         nFaces[uncompactAllPatchI],
01695                         startFaceI
01696                     )
01697                 );
01698 
01699                 // Record new index in allPatches
01700                 from1ToAllPatches[patch1] = allPatchI;
01701 
01702                 startFaceI += nFaces[uncompactAllPatchI];
01703 
01704                 allPatchI++;
01705             }
01706         }
01707     }
01708 
01709     allPatches.setSize(allPatchI);
01710 
01711 
01712     // Construct map information before changing mesh0 primitives
01713     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01714 
01715     autoPtr<mapAddedPolyMesh> mapPtr
01716     (
01717         new mapAddedPolyMesh
01718         (
01719             mesh0.nPoints(),
01720             mesh0.nFaces(),
01721             mesh0.nCells(),
01722 
01723             mesh1.nPoints(),
01724             mesh1.nFaces(),
01725             mesh1.nCells(),
01726 
01727             from0ToAllPoints,
01728             from0ToAllFaces,
01729             identity(mesh0.nCells()),
01730 
01731             from1ToAllPoints,
01732             from1ToAllFaces,
01733             from1ToAllCells,
01734 
01735             from0ToAllPatches,
01736             from1ToAllPatches,
01737 
01738             mesh0PatchSizes,
01739             mesh0PatchStarts
01740         )
01741     );
01742 
01743 
01744 
01745     // Now we have extracted all information from all meshes.
01746     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01747 
01748     labelList patchSizes(getPatchSizes(allPatches));
01749     labelList patchStarts(getPatchStarts(allPatches));
01750 
01751     mesh0.resetMotion();    // delete any oldPoints.
01752     mesh0.resetPrimitives
01753     (
01754         xferMove(allPoints),
01755         xferMove(allFaces),
01756         xferMove(allOwner),
01757         xferMove(allNeighbour),
01758         patchSizes,     // size
01759         patchStarts,    // patchstarts
01760         validBoundary   // boundary valid?
01761     );
01762 
01763     // Add zones to new mesh.
01764     mesh0.pointZones().clear();
01765     mesh0.faceZones().clear();
01766     mesh0.cellZones().clear();
01767     addZones
01768     (
01769         pointZoneNames,
01770         pzPoints,
01771 
01772         faceZoneNames,
01773         fzFaces,
01774         fzFlips,
01775 
01776         cellZoneNames,
01777         czCells,
01778         mesh0
01779     );
01780 
01781     return mapPtr;
01782 }
01783 
01784 
01785 Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
01786 (
01787     const polyMesh& mesh,
01788     const scalar mergeDist
01789 )
01790 {
01791     const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
01792     const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
01793 
01794     // Because of adding the missing pieces e.g. when redistributing a mesh
01795     // it can be that there are multiple points on the same processor that
01796     // refer to the same shared point.
01797 
01798     // Invert point-to-shared addressing
01799     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01800 
01801     Map<labelList> sharedToMesh(sharedPointLabels.size());
01802 
01803     label nMultiple = 0;
01804 
01805     forAll(sharedPointLabels, i)
01806     {
01807         label pointI = sharedPointLabels[i];
01808 
01809         label sharedI = sharedPointAddr[i];
01810 
01811         Map<labelList>::iterator iter = sharedToMesh.find(sharedI);
01812 
01813         if (iter != sharedToMesh.end())
01814         {
01815             // sharedI already used by other point. Add this one.
01816 
01817             nMultiple++;
01818 
01819             labelList& connectedPointLabels = iter();
01820 
01821             label sz = connectedPointLabels.size();
01822 
01823             // Check just to make sure.
01824             if (findIndex(connectedPointLabels, pointI) != -1)
01825             {
01826                 FatalErrorIn("polyMeshAdder::findSharedPoints(..)")
01827                     << "Duplicate point in sharedPoint addressing." << endl
01828                     << "When trying to add point " << pointI << " on shared "
01829                     << sharedI  << " with connected points "
01830                     << connectedPointLabels
01831                     << abort(FatalError);
01832             }
01833 
01834             connectedPointLabels.setSize(sz+1);
01835             connectedPointLabels[sz] = pointI;
01836         }
01837         else
01838         {
01839             sharedToMesh.insert(sharedI, labelList(1, pointI));
01840         }
01841     }
01842 
01843 
01844     // Assign single master for every shared with multiple geometric points
01845     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01846 
01847     Map<label> pointToMaster(nMultiple);
01848 
01849     forAllConstIter(Map<labelList>, sharedToMesh, iter)
01850     {
01851         const labelList& connectedPointLabels = iter();
01852 
01853         //Pout<< "For shared:" << iter.key()
01854         //    << " found points:" << connectedPointLabels
01855         //    << " at coords:"
01856         //    <<  pointField(mesh.points(), connectedPointLabels) << endl;
01857 
01858         if (connectedPointLabels.size() > 1)
01859         {
01860             const pointField connectedPoints
01861             (
01862                 mesh.points(),
01863                 connectedPointLabels
01864             );
01865 
01866             labelList toMergedPoints;
01867             pointField mergedPoints;
01868             bool hasMerged = Foam::mergePoints
01869             (
01870                 connectedPoints,
01871                 mergeDist,
01872                 false,
01873                 toMergedPoints,
01874                 mergedPoints
01875             );
01876 
01877             if (hasMerged)
01878             {
01879                 // Invert toMergedPoints
01880                 const labelListList mergeSets
01881                 (
01882                     invertOneToMany
01883                     (
01884                         mergedPoints.size(),
01885                         toMergedPoints
01886                     )
01887                 );
01888 
01889                 // Find master for valid merges
01890                 forAll(mergeSets, setI)
01891                 {
01892                     const labelList& mergeSet = mergeSets[setI];
01893 
01894                     if (mergeSet.size() > 1)
01895                     {
01896                         // Pick lowest numbered point
01897                         label masterPointI = labelMax;
01898 
01899                         forAll(mergeSet, i)
01900                         {
01901                             label pointI = connectedPointLabels[mergeSet[i]];
01902 
01903                             masterPointI = min(masterPointI, pointI);
01904                         }
01905 
01906                         forAll(mergeSet, i)
01907                         {
01908                             label pointI = connectedPointLabels[mergeSet[i]];
01909 
01910                             //Pout<< "Merging point " << pointI
01911                             //    << " at " << mesh.points()[pointI]
01912                             //    << " into master point "
01913                             //    << masterPointI
01914                             //    << " at " << mesh.points()[masterPointI]
01915                             //    << endl;
01916 
01917                             pointToMaster.insert(pointI, masterPointI);
01918                         }
01919                     }
01920                 }
01921             }
01922         }
01923     }
01924 
01925     //- Old: geometric merging. Causes problems for two close shared points.
01926     //labelList sharedToMerged;
01927     //pointField mergedPoints;
01928     //bool hasMerged = Foam::mergePoints
01929     //(
01930     //    pointField
01931     //    (
01932     //        mesh.points(),
01933     //        sharedPointLabels
01934     //    ),
01935     //    mergeDist,
01936     //    false,
01937     //    sharedToMerged,
01938     //    mergedPoints
01939     //);
01940     //
01943     //
01944     //Map<label> pointToMaster(10*sharedToMerged.size());
01945     //
01946     //if (hasMerged)
01947     //{
01948     //    labelListList mergeSets
01949     //    (
01950     //        invertOneToMany
01951     //        (
01952     //            sharedToMerged.size(),
01953     //            sharedToMerged
01954     //        )
01955     //    );
01956     //
01957     //    label nMergeSets = 0;
01958     //
01959     //    forAll(mergeSets, setI)
01960     //    {
01961     //        const labelList& mergeSet = mergeSets[setI];
01962     //
01963     //        if (mergeSet.size() > 1)
01964     //        {
01965     //            // Take as master the shared point with the lowest mesh
01966     //            // point label. (rather arbitrarily - could use max or
01967     //            // any other one of the points)
01968     //
01969     //            nMergeSets++;
01970     //
01971     //            label masterI = labelMax;
01972     //
01973     //            forAll(mergeSet, i)
01974     //            {
01975     //                label sharedI = mergeSet[i];
01976     //
01977     //                masterI = min(masterI, sharedPointLabels[sharedI]);
01978     //            }
01979     //
01980     //            forAll(mergeSet, i)
01981     //            {
01982     //                label sharedI = mergeSet[i];
01983     //
01984     //                pointToMaster.insert(sharedPointLabels[sharedI], masterI);
01985     //            }
01986     //        }
01987     //    }
01988     //
01989     //    //if (debug)
01990     //    //{
01991     //    //    Pout<< "polyMeshAdder : merging:"
01992     //    //        << pointToMaster.size() << " into " << nMergeSets
01993     //    //        << " sets." << endl;
01994     //    //}
01995     //}
01996 
01997     return pointToMaster;
01998 }
01999 
02000 
02001 void Foam::polyMeshAdder::mergePoints
02002 (
02003     const polyMesh& mesh,
02004     const Map<label>& pointToMaster,
02005     polyTopoChange& meshMod
02006 )
02007 {
02008     // Remove all non-master points.
02009     forAll(mesh.points(), pointI)
02010     {
02011         Map<label>::const_iterator iter = pointToMaster.find(pointI);
02012 
02013         if (iter != pointToMaster.end())
02014         {
02015             if (iter() != pointI)
02016             {
02017                 meshMod.removePoint(pointI, iter());
02018             }
02019         }
02020     }
02021 
02022     // Modify faces for points. Note: could use pointFaces here but want to
02023     // avoid addressing calculation.
02024     const faceList& faces = mesh.faces();
02025 
02026     forAll(faces, faceI)
02027     {
02028         const face& f = faces[faceI];
02029 
02030         bool hasMerged = false;
02031 
02032         forAll(f, fp)
02033         {
02034             label pointI = f[fp];
02035 
02036             Map<label>::const_iterator iter = pointToMaster.find(pointI);
02037 
02038             if (iter != pointToMaster.end())
02039             {
02040                 if (iter() != pointI)
02041                 {
02042                     hasMerged = true;
02043                     break;
02044                 }
02045             }
02046         }
02047 
02048         if (hasMerged)
02049         {
02050             face newF(f);
02051 
02052             forAll(f, fp)
02053             {
02054                 label pointI = f[fp];
02055 
02056                 Map<label>::const_iterator iter = pointToMaster.find(pointI);
02057 
02058                 if (iter != pointToMaster.end())
02059                 {
02060                     newF[fp] = iter();
02061                 }
02062             }
02063 
02064             label patchID = mesh.boundaryMesh().whichPatch(faceI);
02065             label nei = (patchID == -1 ? mesh.faceNeighbour()[faceI] : -1);
02066             label zoneID = mesh.faceZones().whichZone(faceI);
02067             bool zoneFlip = false;
02068 
02069             if (zoneID >= 0)
02070             {
02071                 const faceZone& fZone = mesh.faceZones()[zoneID];
02072                 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
02073             }
02074 
02075             meshMod.setAction
02076             (
02077                 polyModifyFace
02078                 (
02079                     newF,                       // modified face
02080                     faceI,                      // label of face
02081                     mesh.faceOwner()[faceI],    // owner
02082                     nei,                        // neighbour
02083                     false,                      // face flip
02084                     patchID,                    // patch for face
02085                     false,                      // remove from zone
02086                     zoneID,                     // zone for face
02087                     zoneFlip                    // face flip in zone
02088                 )
02089             );
02090         }
02091     }
02092 }
02093 
02094 
02095 // ************************************************************************* //
Copyright © 2000-2009 OpenCFD Ltd