1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*----------------------------------------------------------------------------*/
26 #include "polyMeshAdder.H"
27 #include "mapAddedPolyMesh.H"
29 #include "faceCoupleInfo.H"
30 #include "processorPolyPatch.H"
31 #include "SortableList.H"
33 #include "globalMeshData.H"
34 #include "mergePoints.H"
35 #include "polyModifyFace.H"
36 #include "polyRemovePoint.H"
37 #include "polyTopoChange.H"
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 //- Append all mapped elements of a list to a DynamicList
42 void Foam::polyMeshAdder::append
46 DynamicList<label>& dynLst
49 dynLst.setCapacity(dynLst.size() + lst.size());
53 label newElem = map[lst[i]];
57 dynLst.append(newElem);
63 //- Append all mapped elements of a list to a DynamicList
64 void Foam::polyMeshAdder::append
68 const SortableList<label>& sortedLst,
69 DynamicList<label>& dynLst
72 dynLst.setSize(dynLst.size() + lst.size());
76 label newElem = map[lst[i]];
78 if (newElem != -1 && findSortedIndex(sortedLst, newElem) == -1)
80 dynLst.append(newElem);
86 // Get index of patch in new set of patchnames/types
87 Foam::label Foam::polyMeshAdder::patchIndex
90 DynamicList<word>& allPatchNames,
91 DynamicList<word>& allPatchTypes
94 // Find the patch name on the list. If the patch is already there
95 // and patch types match, return index
96 const word& pType = p.type();
97 const word& pName = p.name();
99 label patchI = findIndex(allPatchNames, pName);
103 // Patch not found. Append to the list
104 allPatchNames.append(pName);
105 allPatchTypes.append(pType);
107 return allPatchNames.size() - 1;
109 else if (allPatchTypes[patchI] == pType)
111 // Found name and types match
116 // Found the name, but type is different
118 // Duplicate name is not allowed. Create a composite name from the
119 // patch name and case name
120 const word& caseName = p.boundaryMesh().mesh().time().caseName();
122 allPatchNames.append(pName + "_" + caseName);
123 allPatchTypes.append(pType);
125 Pout<< "label patchIndex(const polyPatch& p) : "
126 << "Patch " << p.index() << " named "
127 << pName << " in mesh " << caseName
128 << " already exists, but patch types"
129 << " do not match.\nCreating a composite name as "
130 << allPatchNames[allPatchNames.size() - 1] << endl;
132 return allPatchNames.size() - 1;
137 // Get index of zone in new set of zone names
138 Foam::label Foam::polyMeshAdder::zoneIndex
141 DynamicList<word>& names
144 label zoneI = findIndex(names, curName);
152 // Not found. Add new name to the list
153 names.append(curName);
155 return names.size() - 1;
160 void Foam::polyMeshAdder::mergePatchNames
162 const polyBoundaryMesh& patches0,
163 const polyBoundaryMesh& patches1,
165 DynamicList<word>& allPatchNames,
166 DynamicList<word>& allPatchTypes,
168 labelList& from1ToAllPatches,
169 labelList& fromAllTo1Patches
172 // Insert the mesh0 patches and zones
173 append(patches0.names(), allPatchNames);
174 append(patches0.types(), allPatchTypes);
179 // Patches from 0 are taken over as is; those from 1 get either merged
180 // (if they share name and type) or appended.
181 // Empty patches are filtered out much much later on.
183 // Add mesh1 patches and build map both ways.
184 from1ToAllPatches.setSize(patches1.size());
186 forAll(patches1, patchI)
188 from1ToAllPatches[patchI] = patchIndex
195 allPatchTypes.shrink();
196 allPatchNames.shrink();
198 // Invert 1 to all patch map
199 fromAllTo1Patches.setSize(allPatchNames.size());
200 fromAllTo1Patches = -1;
202 forAll(from1ToAllPatches, i)
204 fromAllTo1Patches[from1ToAllPatches[i]] = i;
209 Foam::labelList Foam::polyMeshAdder::getPatchStarts
211 const polyBoundaryMesh& patches
214 labelList patchStarts(patches.size());
215 forAll(patches, patchI)
217 patchStarts[patchI] = patches[patchI].start();
223 Foam::labelList Foam::polyMeshAdder::getPatchSizes
225 const polyBoundaryMesh& patches
228 labelList patchSizes(patches.size());
229 forAll(patches, patchI)
231 patchSizes[patchI] = patches[patchI].size();
237 Foam::List<Foam::polyPatch*> Foam::polyMeshAdder::combinePatches
239 const polyMesh& mesh0,
240 const polyMesh& mesh1,
241 const polyBoundaryMesh& allBoundaryMesh,
242 const label nAllPatches,
243 const labelList& fromAllTo1Patches,
245 const label nInternalFaces,
246 const labelList& nFaces,
248 labelList& from0ToAllPatches,
249 labelList& from1ToAllPatches
252 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
253 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
256 // Compacted new patch list.
257 DynamicList<polyPatch*> allPatches(nAllPatches);
260 // Map from 0 to all patches (since gets compacted)
261 from0ToAllPatches.setSize(patches0.size());
262 from0ToAllPatches = -1;
264 label startFaceI = nInternalFaces;
266 // Copy patches0 with new sizes. First patches always come from
267 // mesh0 and will always be present.
268 for (label patchI = 0; patchI < patches0.size(); patchI++)
270 // Originates from mesh0. Clone with new size & filter out empty
272 label filteredPatchI;
274 if (nFaces[patchI] == 0 && isA<processorPolyPatch>(patches0[patchI]))
276 //Pout<< "Removing zero sized mesh0 patch "
277 // << patches0[patchI].name() << endl;
282 filteredPatchI = allPatches.size();
286 patches0[patchI].clone
294 startFaceI += nFaces[patchI];
297 // Record new index in allPatches
298 from0ToAllPatches[patchI] = filteredPatchI;
300 // Check if patch was also in mesh1 and update its addressing if so.
301 if (fromAllTo1Patches[patchI] != -1)
303 from1ToAllPatches[fromAllTo1Patches[patchI]] = filteredPatchI;
307 // Copy unique patches of mesh1.
308 forAll(from1ToAllPatches, patchI)
310 label allPatchI = from1ToAllPatches[patchI];
312 if (allPatchI >= patches0.size())
314 // Patch has not been merged with any mesh0 patch.
316 label filteredPatchI;
320 nFaces[allPatchI] == 0
321 && isA<processorPolyPatch>(patches1[patchI])
324 //Pout<< "Removing zero sized mesh1 patch "
325 // << patches1[patchI].name() << endl;
330 filteredPatchI = allPatches.size();
334 patches1[patchI].clone
342 startFaceI += nFaces[allPatchI];
345 from1ToAllPatches[patchI] = filteredPatchI;
355 Foam::labelList Foam::polyMeshAdder::getFaceOrder
357 const cellList& cells,
358 const label nInternalFaces,
359 const labelList& owner,
360 const labelList& neighbour
363 labelList oldToNew(owner.size(), -1);
365 // Leave boundary faces in order
366 for (label faceI = nInternalFaces; faceI < owner.size(); faceI++)
368 oldToNew[faceI] = faceI;
371 // First unassigned face
376 const labelList& cFaces = cells[cellI];
378 SortableList<label> nbr(cFaces.size());
382 label faceI = cFaces[i];
384 label nbrCellI = neighbour[faceI];
388 // Internal face. Get cell on other side.
389 if (nbrCellI == cellI)
391 nbrCellI = owner[faceI];
394 if (cellI < nbrCellI)
401 // nbrCell is master. Let it handle this face.
407 // External face. Do later.
418 oldToNew[cFaces[nbr.indices()[i]]] = newFaceI++;
424 // Check done all faces.
425 forAll(oldToNew, faceI)
427 if (oldToNew[faceI] == -1)
431 "polyMeshAdder::getFaceOrder"
432 "(const cellList&, const label, const labelList&"
433 ", const labelList&) const"
434 ) << "Did not determine new position"
435 << " for face " << faceI
436 << abort(FatalError);
444 // Extends face f with split points. cutEdgeToPoints gives for every
445 // edge the points introduced inbetween the endpoints.
446 void Foam::polyMeshAdder::insertVertices
448 const edgeLookup& cutEdgeToPoints,
449 const Map<label>& meshToMaster,
450 const labelList& masterToCutPoints,
453 DynamicList<label>& workFace,
459 // Check any edge for being cut (check on the cut so takes account
460 // for any point merging on the cut)
464 label v0 = masterF[fp];
465 label v1 = masterF.nextLabel(fp);
467 // Copy existing face point
468 workFace.append(allF[fp]);
470 // See if any edge between v0,v1
472 Map<label>::const_iterator v0Fnd = meshToMaster.find(v0);
473 if (v0Fnd != meshToMaster.end())
475 Map<label>::const_iterator v1Fnd = meshToMaster.find(v1);
476 if (v1Fnd != meshToMaster.end())
478 // Get edge in cutPoint numbering
481 masterToCutPoints[v0Fnd()],
482 masterToCutPoints[v1Fnd()]
485 edgeLookup::const_iterator iter = cutEdgeToPoints.find(cutEdge);
487 if (iter != cutEdgeToPoints.end())
489 const edge& e = iter.key();
490 const labelList& addedPoints = iter();
492 // cutPoints first in allPoints so no need for renumbering
493 if (e[0] == cutEdge[0])
495 forAll(addedPoints, i)
497 workFace.append(addedPoints[i]);
502 forAllReverse(addedPoints, i)
504 workFace.append(addedPoints[i]);
512 if (workFace.size() != allF.size())
514 allF.transfer(workFace);
519 // Adds primitives (cells, faces, points)
524 // - all uncoupled of mesh0
525 // - all coupled faces
526 // - all uncoupled of mesh1
529 // - all uncoupled of mesh0
530 // - all uncoupled of mesh1
531 void Foam::polyMeshAdder::mergePrimitives
533 const polyMesh& mesh0,
534 const polyMesh& mesh1,
535 const faceCoupleInfo& coupleInfo,
537 const label nAllPatches, // number of patches in the new mesh
538 const labelList& fromAllTo1Patches,
539 const labelList& from1ToAllPatches,
541 pointField& allPoints,
542 labelList& from0ToAllPoints,
543 labelList& from1ToAllPoints,
547 labelList& allNeighbour,
548 label& nInternalFaces,
549 labelList& nFacesPerPatch,
552 labelList& from0ToAllFaces,
553 labelList& from1ToAllFaces,
554 labelList& from1ToAllCells
557 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
558 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
560 const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
561 const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
562 const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
568 // Storage for new points
569 allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
572 from0ToAllPoints.setSize(mesh0.nPoints());
573 from0ToAllPoints = -1;
574 from1ToAllPoints.setSize(mesh1.nPoints());
575 from1ToAllPoints = -1;
577 // Copy coupled points (on cut)
579 const pointField& cutPoints = coupleInfo.cutPoints();
581 //const labelListList& cutToMasterPoints =
582 // coupleInfo.cutToMasterPoints();
583 labelListList cutToMasterPoints
588 coupleInfo.masterToCutPoints()
592 //const labelListList& cutToSlavePoints =
593 // coupleInfo.cutToSlavePoints();
594 labelListList cutToSlavePoints
599 coupleInfo.slaveToCutPoints()
605 allPoints[allPointI] = cutPoints[i];
607 // Mark all master and slave points referring to this point.
609 const labelList& masterPoints = cutToMasterPoints[i];
611 forAll(masterPoints, j)
613 label mesh0PointI = masterPatch.meshPoints()[masterPoints[j]];
614 from0ToAllPoints[mesh0PointI] = allPointI;
617 const labelList& slavePoints = cutToSlavePoints[i];
619 forAll(slavePoints, j)
621 label mesh1PointI = slavePatch.meshPoints()[slavePoints[j]];
622 from1ToAllPoints[mesh1PointI] = allPointI;
628 // Add uncoupled mesh0 points
629 forAll(mesh0.points(), pointI)
631 if (from0ToAllPoints[pointI] == -1)
633 allPoints[allPointI] = mesh0.points()[pointI];
634 from0ToAllPoints[pointI] = allPointI;
639 // Add uncoupled mesh1 points
640 forAll(mesh1.points(), pointI)
642 if (from1ToAllPoints[pointI] == -1)
644 allPoints[allPointI] = mesh1.points()[pointI];
645 from1ToAllPoints[pointI] = allPointI;
650 allPoints.setSize(allPointI);
657 nFacesPerPatch.setSize(nAllPatches);
660 // Storage for faces and owner/neighbour
661 allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
662 allOwner.setSize(allFaces.size());
664 allNeighbour.setSize(allFaces.size());
668 from0ToAllFaces.setSize(mesh0.nFaces());
669 from0ToAllFaces = -1;
670 from1ToAllFaces.setSize(mesh1.nFaces());
671 from1ToAllFaces = -1;
673 // Copy mesh0 internal faces (always uncoupled)
674 for (label faceI = 0; faceI < mesh0.nInternalFaces(); faceI++)
676 allFaces[allFaceI] = renumber(from0ToAllPoints, mesh0.faces()[faceI]);
677 allOwner[allFaceI] = mesh0.faceOwner()[faceI];
678 allNeighbour[allFaceI] = mesh0.faceNeighbour()[faceI];
679 from0ToAllFaces[faceI] = allFaceI++;
682 // Copy coupled faces. Every coupled face has an equivalent master and
683 // slave. Also uncount as boundary faces all the newly coupled faces.
684 const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
685 const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
689 label masterFaceI = cutToMasterFaces[i];
691 label mesh0FaceI = masterPatch.addressing()[masterFaceI];
693 if (from0ToAllFaces[mesh0FaceI] == -1)
695 // First occurrence of face
696 from0ToAllFaces[mesh0FaceI] = allFaceI;
698 // External face becomes internal so uncount
699 label patch0 = patches0.whichPatch(mesh0FaceI);
700 nFacesPerPatch[patch0]--;
703 label slaveFaceI = cutToSlaveFaces[i];
705 label mesh1FaceI = slavePatch.addressing()[slaveFaceI];
707 if (from1ToAllFaces[mesh1FaceI] == -1)
709 from1ToAllFaces[mesh1FaceI] = allFaceI;
711 label patch1 = patches1.whichPatch(mesh1FaceI);
712 nFacesPerPatch[from1ToAllPatches[patch1]]--;
715 // Copy cut face (since cutPoints are copied first no renumbering
717 allFaces[allFaceI] = cutFaces[i];
718 allOwner[allFaceI] = mesh0.faceOwner()[mesh0FaceI];
719 allNeighbour[allFaceI] = mesh1.faceOwner()[mesh1FaceI] + mesh0.nCells();
724 // Copy mesh1 internal faces (always uncoupled)
725 for (label faceI = 0; faceI < mesh1.nInternalFaces(); faceI++)
727 allFaces[allFaceI] = renumber(from1ToAllPoints, mesh1.faces()[faceI]);
728 allOwner[allFaceI] = mesh1.faceOwner()[faceI] + mesh0.nCells();
729 allNeighbour[allFaceI] = mesh1.faceNeighbour()[faceI] + mesh0.nCells();
730 from1ToAllFaces[faceI] = allFaceI++;
733 nInternalFaces = allFaceI;
735 // Copy (unmarked/uncoupled) external faces in new order.
736 for (label allPatchI = 0; allPatchI < nAllPatches; allPatchI++)
738 if (allPatchI < patches0.size())
740 // Patch is present in mesh0
741 const polyPatch& pp = patches0[allPatchI];
743 nFacesPerPatch[allPatchI] += pp.size();
745 label faceI = pp.start();
749 if (from0ToAllFaces[faceI] == -1)
751 // Is uncoupled face since has not yet been dealt with
752 allFaces[allFaceI] = renumber
757 allOwner[allFaceI] = mesh0.faceOwner()[faceI];
758 allNeighbour[allFaceI] = -1;
760 from0ToAllFaces[faceI] = allFaceI++;
765 if (fromAllTo1Patches[allPatchI] != -1)
767 // Patch is present in mesh1
768 const polyPatch& pp = patches1[fromAllTo1Patches[allPatchI]];
770 nFacesPerPatch[allPatchI] += pp.size();
772 label faceI = pp.start();
776 if (from1ToAllFaces[faceI] == -1)
779 allFaces[allFaceI] = renumber
785 mesh1.faceOwner()[faceI]
787 allNeighbour[allFaceI] = -1;
789 from1ToAllFaces[faceI] = allFaceI++;
795 allFaces.setSize(allFaceI);
796 allOwner.setSize(allFaceI);
797 allNeighbour.setSize(allFaceI);
800 // So now we have all ok for one-to-one mapping.
801 // For split slace faces:
802 // - mesh consistent with slave side
803 // - mesh not consistent with owner side. It is not zipped up, the
804 // original faces need edges split.
806 // Use brute force to prevent having to calculate addressing:
807 // - get map from master edge to split edges.
808 // - check all faces to find any edge that is split.
810 // From two cut-points to labels of cut-points inbetween.
811 // (in order: from e[0] to e[1]
812 const edgeLookup& cutEdgeToPoints = coupleInfo.cutEdgeToPoints();
814 // Get map of master face (in mesh labels) that are in cut. These faces
815 // do not need to be renumbered.
816 labelHashSet masterCutFaces(cutToMasterFaces.size());
817 forAll(cutToMasterFaces, i)
819 label meshFaceI = masterPatch.addressing()[cutToMasterFaces[i]];
821 masterCutFaces.insert(meshFaceI);
824 DynamicList<label> workFace(100);
826 forAll(from0ToAllFaces, face0)
828 if (!masterCutFaces.found(face0))
830 label allFaceI = from0ToAllFaces[face0];
835 masterPatch.meshPointMap(),
836 coupleInfo.masterToCutPoints(),
837 mesh0.faces()[face0],
845 // Same for slave face
847 labelHashSet slaveCutFaces(cutToSlaveFaces.size());
848 forAll(cutToSlaveFaces, i)
850 label meshFaceI = slavePatch.addressing()[cutToSlaveFaces[i]];
852 slaveCutFaces.insert(meshFaceI);
855 forAll(from1ToAllFaces, face1)
857 if (!slaveCutFaces.found(face1))
859 label allFaceI = from1ToAllFaces[face1];
864 slavePatch.meshPointMap(),
865 coupleInfo.slaveToCutPoints(),
866 mesh1.faces()[face1],
875 // Now we have a full facelist and owner/neighbour addressing.
881 from1ToAllCells.setSize(mesh1.nCells());
882 from1ToAllCells = -1;
884 forAll(mesh1.cells(), i)
886 from1ToAllCells[i] = i + mesh0.nCells();
889 // Make cells (= cell-face addressing)
890 nCells = mesh0.nCells() + mesh1.nCells();
891 cellList allCells(nCells);
892 primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
894 // Reorder faces for upper-triangular order.
906 inplaceReorder(oldToNew, allFaces);
907 inplaceReorder(oldToNew, allOwner);
908 inplaceReorder(oldToNew, allNeighbour);
909 inplaceRenumber(oldToNew, from0ToAllFaces);
910 inplaceRenumber(oldToNew, from1ToAllFaces);
914 void Foam::polyMeshAdder::mergePointZones
916 const pointZoneMesh& pz0,
917 const pointZoneMesh& pz1,
918 const labelList& from0ToAllPoints,
919 const labelList& from1ToAllPoints,
921 DynamicList<word>& zoneNames,
922 labelList& from1ToAll,
923 List<DynamicList<label> >& pzPoints
926 zoneNames.setCapacity(pz0.size() + pz1.size());
929 append(pz0.names(), zoneNames);
931 from1ToAll.setSize(pz1.size());
935 from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
939 // Point labels per merged zone
940 pzPoints.setSize(zoneNames.size());
944 append(from0ToAllPoints, pz0[zoneI], pzPoints[zoneI]);
947 // Get sorted zone contents for duplicate element recognition
948 PtrList<SortableList<label> > pzPointsSorted(pzPoints.size());
949 forAll(pzPoints, zoneI)
954 new SortableList<label>(pzPoints[zoneI])
958 // Now we have full addressing for points so do the pointZones of mesh1.
961 // Relabel all points of zone and add to correct pzPoints.
962 label allZoneI = from1ToAll[zoneI];
968 pzPointsSorted[allZoneI],
975 pzPoints[i].shrink();
980 void Foam::polyMeshAdder::mergeFaceZones
982 const faceZoneMesh& fz0,
983 const faceZoneMesh& fz1,
984 const labelList& from0ToAllFaces,
985 const labelList& from1ToAllFaces,
987 DynamicList<word>& zoneNames,
988 labelList& from1ToAll,
989 List<DynamicList<label> >& fzFaces,
990 List<DynamicList<bool> >& fzFlips
993 zoneNames.setCapacity(fz0.size() + fz1.size());
995 append(fz0.names(), zoneNames);
997 from1ToAll.setSize(fz1.size());
1001 from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
1006 // Create temporary lists for faceZones.
1007 fzFaces.setSize(zoneNames.size());
1008 fzFlips.setSize(zoneNames.size());
1011 DynamicList<label>& newZone = fzFaces[zoneI];
1012 DynamicList<bool>& newFlip = fzFlips[zoneI];
1014 newZone.setCapacity(fz0[zoneI].size());
1015 newFlip.setCapacity(newZone.size());
1017 const labelList& addressing = fz0[zoneI];
1018 const boolList& flipMap = fz0[zoneI].flipMap();
1020 forAll(addressing, i)
1022 label faceI = addressing[i];
1024 if (from0ToAllFaces[faceI] != -1)
1026 newZone.append(from0ToAllFaces[faceI]);
1027 newFlip.append(flipMap[i]);
1032 // Get sorted zone contents for duplicate element recognition
1033 PtrList<SortableList<label> > fzFacesSorted(fzFaces.size());
1034 forAll(fzFaces, zoneI)
1039 new SortableList<label>(fzFaces[zoneI])
1043 // Now we have full addressing for faces so do the faceZones of mesh1.
1046 label allZoneI = from1ToAll[zoneI];
1048 DynamicList<label>& newZone = fzFaces[allZoneI];
1049 const SortableList<label>& newZoneSorted = fzFacesSorted[allZoneI];
1050 DynamicList<bool>& newFlip = fzFlips[allZoneI];
1052 newZone.setCapacity(newZone.size() + fz1[zoneI].size());
1053 newFlip.setCapacity(newZone.size());
1055 const labelList& addressing = fz1[zoneI];
1056 const boolList& flipMap = fz1[zoneI].flipMap();
1058 forAll(addressing, i)
1060 label faceI = addressing[i];
1061 label allFaceI = from1ToAllFaces[faceI];
1066 && findSortedIndex(newZoneSorted, allFaceI) == -1
1069 newZone.append(allFaceI);
1070 newFlip.append(flipMap[i]);
1077 fzFaces[i].shrink();
1078 fzFlips[i].shrink();
1083 void Foam::polyMeshAdder::mergeCellZones
1085 const cellZoneMesh& cz0,
1086 const cellZoneMesh& cz1,
1087 const labelList& from1ToAllCells,
1089 DynamicList<word>& zoneNames,
1090 labelList& from1ToAll,
1091 List<DynamicList<label> >& czCells
1094 zoneNames.setCapacity(cz0.size() + cz1.size());
1096 append(cz0.names(), zoneNames);
1098 from1ToAll.setSize(cz1.size());
1101 from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
1106 // Create temporary lists for cellZones.
1107 czCells.setSize(zoneNames.size());
1110 // Insert mesh0 cells
1111 append(cz0[zoneI], czCells[zoneI]);
1115 // Cell mapping is trivial.
1118 label allZoneI = from1ToAll[zoneI];
1120 append(from1ToAllCells, cz1[zoneI], czCells[allZoneI]);
1125 czCells[i].shrink();
1130 void Foam::polyMeshAdder::mergeZones
1132 const polyMesh& mesh0,
1133 const polyMesh& mesh1,
1134 const labelList& from0ToAllPoints,
1135 const labelList& from0ToAllFaces,
1137 const labelList& from1ToAllPoints,
1138 const labelList& from1ToAllFaces,
1139 const labelList& from1ToAllCells,
1141 DynamicList<word>& pointZoneNames,
1142 List<DynamicList<label> >& pzPoints,
1144 DynamicList<word>& faceZoneNames,
1145 List<DynamicList<label> >& fzFaces,
1146 List<DynamicList<bool> >& fzFlips,
1148 DynamicList<word>& cellZoneNames,
1149 List<DynamicList<label> >& czCells
1152 labelList from1ToAllPZones;
1165 labelList from1ToAllFZones;
1179 labelList from1ToAllCZones;
1193 void Foam::polyMeshAdder::addZones
1195 const DynamicList<word>& pointZoneNames,
1196 const List<DynamicList<label> >& pzPoints,
1198 const DynamicList<word>& faceZoneNames,
1199 const List<DynamicList<label> >& fzFaces,
1200 const List<DynamicList<bool> >& fzFlips,
1202 const DynamicList<word>& cellZoneNames,
1203 const List<DynamicList<label> >& czCells,
1208 List<pointZone*> pZones(pzPoints.size());
1211 pZones[i] = new pointZone
1220 List<faceZone*> fZones(fzFaces.size());
1223 fZones[i] = new faceZone
1233 List<cellZone*> cZones(czCells.size());
1236 cZones[i] = new cellZone
1255 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1257 // Returns new mesh and sets
1258 // - map from new cell/face/point/patch to either mesh0 or mesh1
1260 // mesh0Faces/mesh1Faces: corresponding faces on both meshes.
1261 Foam::autoPtr<Foam::polyMesh> Foam::polyMeshAdder::add
1264 const polyMesh& mesh0,
1265 const polyMesh& mesh1,
1266 const faceCoupleInfo& coupleInfo,
1267 autoPtr<mapAddedPolyMesh>& mapPtr
1270 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1271 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1274 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1275 DynamicList<word> allPatchTypes(allPatchNames.size());
1278 labelList from1ToAllPatches(patches1.size());
1279 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1293 pointField allPoints;
1295 // Map from mesh0/1 points to allPoints.
1296 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1297 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1301 label nInternalFaces;
1305 labelList allNeighbour;
1309 labelList nFaces(allPatchNames.size(), 0);
1312 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1313 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1316 labelList from1ToAllCells(mesh1.nCells(), -1);
1324 allPatchNames.size(),
1348 DynamicList<word> pointZoneNames;
1349 List<DynamicList<label> > pzPoints;
1351 DynamicList<word> faceZoneNames;
1352 List<DynamicList<label> > fzFaces;
1353 List<DynamicList<bool> > fzFlips;
1355 DynamicList<word> cellZoneNames;
1356 List<DynamicList<label> > czCells;
1385 // Map from 0 to all patches (since gets compacted)
1386 labelList from0ToAllPatches(patches0.size(), -1);
1388 List<polyPatch*> allPatches
1394 patches0, // Should be boundaryMesh() on new mesh.
1395 allPatchNames.size(),
1397 mesh0.nInternalFaces()
1398 + mesh1.nInternalFaces()
1399 + coupleInfo.cutFaces().size(),
1413 new mapAddedPolyMesh
1425 identity(mesh0.nCells()),
1433 getPatchSizes(patches0),
1434 getPatchStarts(patches0)
1440 // Now we have extracted all information from all meshes.
1441 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1444 autoPtr<polyMesh> tmesh
1449 xferMove(allPoints),
1452 xferMove(allNeighbour)
1455 polyMesh& mesh = tmesh();
1457 // Add zones to new mesh.
1472 // Add patches to new mesh
1473 mesh.addPatches(allPatches);
1479 // Inplace add mesh1 to mesh0
1480 Foam::autoPtr<Foam::mapAddedPolyMesh> Foam::polyMeshAdder::add
1483 const polyMesh& mesh1,
1484 const faceCoupleInfo& coupleInfo,
1485 const bool validBoundary
1488 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1489 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1491 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1492 DynamicList<word> allPatchTypes(allPatchNames.size());
1495 labelList from1ToAllPatches(patches1.size());
1496 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1510 pointField allPoints;
1512 // Map from mesh0/1 points to allPoints.
1513 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1514 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1519 labelList allNeighbour;
1520 label nInternalFaces;
1522 labelList nFaces(allPatchNames.size(), 0);
1526 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1527 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1529 labelList from1ToAllCells(mesh1.nCells(), -1);
1537 allPatchNames.size(),
1561 DynamicList<word> pointZoneNames;
1562 List<DynamicList<label> > pzPoints;
1564 DynamicList<word> faceZoneNames;
1565 List<DynamicList<label> > fzFaces;
1566 List<DynamicList<bool> > fzFlips;
1568 DynamicList<word> cellZoneNames;
1569 List<DynamicList<label> > czCells;
1599 // Store mesh0 patch info before modifying patches0.
1600 labelList mesh0PatchSizes(getPatchSizes(patches0));
1601 labelList mesh0PatchStarts(getPatchStarts(patches0));
1603 // Map from 0 to all patches (since gets compacted)
1604 labelList from0ToAllPatches(patches0.size(), -1);
1606 // Inplace extend mesh0 patches (note that patches0.size() now also
1608 polyBoundaryMesh& allPatches =
1609 const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
1610 allPatches.setSize(allPatchNames.size());
1612 label startFaceI = nInternalFaces;
1614 // Copy patches0 with new sizes. First patches always come from
1615 // mesh0 and will always be present.
1616 label allPatchI = 0;
1618 forAll(from0ToAllPatches, patch0)
1620 // Originates from mesh0. Clone with new size & filter out empty
1623 if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
1625 //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
1627 from0ToAllPatches[patch0] = -1;
1628 // Check if patch was also in mesh1 and update its addressing if so.
1629 if (fromAllTo1Patches[patch0] != -1)
1631 from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1640 allPatches[patch0].clone
1649 // Record new index in allPatches
1650 from0ToAllPatches[patch0] = allPatchI;
1652 // Check if patch was also in mesh1 and update its addressing if so.
1653 if (fromAllTo1Patches[patch0] != -1)
1655 from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchI;
1658 startFaceI += nFaces[patch0];
1664 // Copy unique patches of mesh1.
1665 forAll(from1ToAllPatches, patch1)
1667 label uncompactAllPatchI = from1ToAllPatches[patch1];
1669 if (uncompactAllPatchI >= from0ToAllPatches.size())
1671 // Patch has not been merged with any mesh0 patch.
1675 nFaces[uncompactAllPatchI] == 0
1676 && isA<processorPolyPatch>(patches1[patch1])
1679 //Pout<< "Removing zero sized mesh1 patch "
1680 // << allPatchNames[uncompactAllPatchI] << endl;
1681 from1ToAllPatches[patch1] = -1;
1689 patches1[patch1].clone
1693 nFaces[uncompactAllPatchI],
1698 // Record new index in allPatches
1699 from1ToAllPatches[patch1] = allPatchI;
1701 startFaceI += nFaces[uncompactAllPatchI];
1708 allPatches.setSize(allPatchI);
1711 // Construct map information before changing mesh0 primitives
1712 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1714 autoPtr<mapAddedPolyMesh> mapPtr
1716 new mapAddedPolyMesh
1728 identity(mesh0.nCells()),
1744 // Now we have extracted all information from all meshes.
1745 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1747 labelList patchSizes(getPatchSizes(allPatches));
1748 labelList patchStarts(getPatchStarts(allPatches));
1750 mesh0.resetMotion(); // delete any oldPoints.
1751 mesh0.resetPrimitives
1753 xferMove(allPoints),
1756 xferMove(allNeighbour),
1758 patchStarts, // patchstarts
1759 validBoundary // boundary valid?
1762 // Add zones to new mesh.
1763 mesh0.pointZones().clear();
1764 mesh0.faceZones().clear();
1765 mesh0.cellZones().clear();
1784 Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
1786 const polyMesh& mesh,
1787 const scalar mergeDist
1790 const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
1791 const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
1793 // Because of adding the missing pieces e.g. when redistributing a mesh
1794 // it can be that there are multiple points on the same processor that
1795 // refer to the same shared point.
1797 // Invert point-to-shared addressing
1798 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1800 Map<labelList> sharedToMesh(sharedPointLabels.size());
1802 label nMultiple = 0;
1804 forAll(sharedPointLabels, i)
1806 label pointI = sharedPointLabels[i];
1808 label sharedI = sharedPointAddr[i];
1810 Map<labelList>::iterator iter = sharedToMesh.find(sharedI);
1812 if (iter != sharedToMesh.end())
1814 // sharedI already used by other point. Add this one.
1818 labelList& connectedPointLabels = iter();
1820 label sz = connectedPointLabels.size();
1822 // Check just to make sure.
1823 if (findIndex(connectedPointLabels, pointI) != -1)
1825 FatalErrorIn("polyMeshAdder::findSharedPoints(..)")
1826 << "Duplicate point in sharedPoint addressing." << endl
1827 << "When trying to add point " << pointI << " on shared "
1828 << sharedI << " with connected points "
1829 << connectedPointLabels
1830 << abort(FatalError);
1833 connectedPointLabels.setSize(sz+1);
1834 connectedPointLabels[sz] = pointI;
1838 sharedToMesh.insert(sharedI, labelList(1, pointI));
1843 // Assign single master for every shared with multiple geometric points
1844 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1846 Map<label> pointToMaster(nMultiple);
1848 forAllConstIter(Map<labelList>, sharedToMesh, iter)
1850 const labelList& connectedPointLabels = iter();
1852 //Pout<< "For shared:" << iter.key()
1853 // << " found points:" << connectedPointLabels
1855 // << pointField(mesh.points(), connectedPointLabels) << endl;
1857 if (connectedPointLabels.size() > 1)
1859 const pointField connectedPoints
1862 connectedPointLabels
1865 labelList toMergedPoints;
1866 pointField mergedPoints;
1867 bool hasMerged = Foam::mergePoints
1878 // Invert toMergedPoints
1879 const labelListList mergeSets
1883 mergedPoints.size(),
1888 // Find master for valid merges
1889 forAll(mergeSets, setI)
1891 const labelList& mergeSet = mergeSets[setI];
1893 if (mergeSet.size() > 1)
1895 // Pick lowest numbered point
1896 label masterPointI = labelMax;
1900 label pointI = connectedPointLabels[mergeSet[i]];
1902 masterPointI = min(masterPointI, pointI);
1907 label pointI = connectedPointLabels[mergeSet[i]];
1909 //Pout<< "Merging point " << pointI
1910 // << " at " << mesh.points()[pointI]
1911 // << " into master point "
1913 // << " at " << mesh.points()[masterPointI]
1916 pointToMaster.insert(pointI, masterPointI);
1924 //- Old: geometric merging. Causes problems for two close shared points.
1925 //labelList sharedToMerged;
1926 //pointField mergedPoints;
1927 //bool hasMerged = Foam::mergePoints
1932 // sharedPointLabels
1940 //// Find out which sets of points get merged and create a map from
1941 //// mesh point to unique point.
1943 //Map<label> pointToMaster(10*sharedToMerged.size());
1947 // labelListList mergeSets
1951 // sharedToMerged.size(),
1956 // label nMergeSets = 0;
1958 // forAll(mergeSets, setI)
1960 // const labelList& mergeSet = mergeSets[setI];
1962 // if (mergeSet.size() > 1)
1964 // // Take as master the shared point with the lowest mesh
1965 // // point label. (rather arbitrarily - could use max or
1966 // // any other one of the points)
1970 // label masterI = labelMax;
1972 // forAll(mergeSet, i)
1974 // label sharedI = mergeSet[i];
1976 // masterI = min(masterI, sharedPointLabels[sharedI]);
1979 // forAll(mergeSet, i)
1981 // label sharedI = mergeSet[i];
1983 // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
1990 // // Pout<< "polyMeshAdder : merging:"
1991 // // << pointToMaster.size() << " into " << nMergeSets
1992 // // << " sets." << endl;
1996 return pointToMaster;
2000 void Foam::polyMeshAdder::mergePoints
2002 const polyMesh& mesh,
2003 const Map<label>& pointToMaster,
2004 polyTopoChange& meshMod
2007 // Remove all non-master points.
2008 forAll(mesh.points(), pointI)
2010 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2012 if (iter != pointToMaster.end())
2014 if (iter() != pointI)
2016 meshMod.removePoint(pointI, iter());
2021 // Modify faces for points. Note: could use pointFaces here but want to
2022 // avoid addressing calculation.
2023 const faceList& faces = mesh.faces();
2025 forAll(faces, faceI)
2027 const face& f = faces[faceI];
2029 bool hasMerged = false;
2033 label pointI = f[fp];
2035 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2037 if (iter != pointToMaster.end())
2039 if (iter() != pointI)
2053 label pointI = f[fp];
2055 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2057 if (iter != pointToMaster.end())
2063 label patchID = mesh.boundaryMesh().whichPatch(faceI);
2064 label nei = (patchID == -1 ? mesh.faceNeighbour()[faceI] : -1);
2065 label zoneID = mesh.faceZones().whichZone(faceI);
2066 bool zoneFlip = false;
2070 const faceZone& fZone = mesh.faceZones()[zoneID];
2071 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
2078 newF, // modified face
2079 faceI, // label of face
2080 mesh.faceOwner()[faceI], // owner
2083 patchID, // patch for face
2084 false, // remove from zone
2085 zoneID, // zone for face
2086 zoneFlip // face flip in zone
2094 // ************************************************************************* //