FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

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