1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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 const 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 const 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.last() << 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 allPatchNames.append(patches0.names());
174 allPatchTypes.append(patches0.types());
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 forAll(patches0, 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());
927 zoneNames.append(pz0.names());
929 from1ToAll.setSize(pz1.size());
933 from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
937 // Point labels per merged zone
938 pzPoints.setSize(zoneNames.size());
942 append(from0ToAllPoints, pz0[zoneI], pzPoints[zoneI]);
945 // Get sorted zone contents for duplicate element recognition
946 PtrList<SortableList<label> > pzPointsSorted(pzPoints.size());
947 forAll(pzPoints, zoneI)
952 new SortableList<label>(pzPoints[zoneI])
956 // Now we have full addressing for points so do the pointZones of mesh1.
959 // Relabel all points of zone and add to correct pzPoints.
960 const label allZoneI = from1ToAll[zoneI];
966 pzPointsSorted[allZoneI],
973 pzPoints[i].shrink();
978 void Foam::polyMeshAdder::mergeFaceZones
980 const faceZoneMesh& fz0,
981 const faceZoneMesh& fz1,
982 const labelList& from0ToAllFaces,
983 const labelList& from1ToAllFaces,
985 DynamicList<word>& zoneNames,
986 labelList& from1ToAll,
987 List<DynamicList<label> >& fzFaces,
988 List<DynamicList<bool> >& fzFlips
991 zoneNames.setCapacity(fz0.size() + fz1.size());
992 zoneNames.append(fz0.names());
994 from1ToAll.setSize(fz1.size());
998 from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
1003 // Create temporary lists for faceZones.
1004 fzFaces.setSize(zoneNames.size());
1005 fzFlips.setSize(zoneNames.size());
1008 DynamicList<label>& newZone = fzFaces[zoneI];
1009 DynamicList<bool>& newFlip = fzFlips[zoneI];
1011 newZone.setCapacity(fz0[zoneI].size());
1012 newFlip.setCapacity(newZone.size());
1014 const labelList& addressing = fz0[zoneI];
1015 const boolList& flipMap = fz0[zoneI].flipMap();
1017 forAll(addressing, i)
1019 label faceI = addressing[i];
1021 if (from0ToAllFaces[faceI] != -1)
1023 newZone.append(from0ToAllFaces[faceI]);
1024 newFlip.append(flipMap[i]);
1029 // Get sorted zone contents for duplicate element recognition
1030 PtrList<SortableList<label> > fzFacesSorted(fzFaces.size());
1031 forAll(fzFaces, zoneI)
1036 new SortableList<label>(fzFaces[zoneI])
1040 // Now we have full addressing for faces so do the faceZones of mesh1.
1043 label allZoneI = from1ToAll[zoneI];
1045 DynamicList<label>& newZone = fzFaces[allZoneI];
1046 const SortableList<label>& newZoneSorted = fzFacesSorted[allZoneI];
1047 DynamicList<bool>& newFlip = fzFlips[allZoneI];
1049 newZone.setCapacity(newZone.size() + fz1[zoneI].size());
1050 newFlip.setCapacity(newZone.size());
1052 const labelList& addressing = fz1[zoneI];
1053 const boolList& flipMap = fz1[zoneI].flipMap();
1055 forAll(addressing, i)
1057 label faceI = addressing[i];
1058 label allFaceI = from1ToAllFaces[faceI];
1063 && findSortedIndex(newZoneSorted, allFaceI) == -1
1066 newZone.append(allFaceI);
1067 newFlip.append(flipMap[i]);
1074 fzFaces[i].shrink();
1075 fzFlips[i].shrink();
1080 void Foam::polyMeshAdder::mergeCellZones
1082 const cellZoneMesh& cz0,
1083 const cellZoneMesh& cz1,
1084 const labelList& from1ToAllCells,
1086 DynamicList<word>& zoneNames,
1087 labelList& from1ToAll,
1088 List<DynamicList<label> >& czCells
1091 zoneNames.setCapacity(cz0.size() + cz1.size());
1092 zoneNames.append(cz0.names());
1094 from1ToAll.setSize(cz1.size());
1097 from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
1102 // Create temporary lists for cellZones.
1103 czCells.setSize(zoneNames.size());
1106 // Insert mesh0 cells
1107 czCells[zoneI].append(cz0[zoneI]);
1111 // Cell mapping is trivial.
1114 const label allZoneI = from1ToAll[zoneI];
1116 append(from1ToAllCells, cz1[zoneI], czCells[allZoneI]);
1121 czCells[i].shrink();
1126 void Foam::polyMeshAdder::mergeZones
1128 const polyMesh& mesh0,
1129 const polyMesh& mesh1,
1130 const labelList& from0ToAllPoints,
1131 const labelList& from0ToAllFaces,
1133 const labelList& from1ToAllPoints,
1134 const labelList& from1ToAllFaces,
1135 const labelList& from1ToAllCells,
1137 DynamicList<word>& pointZoneNames,
1138 List<DynamicList<label> >& pzPoints,
1140 DynamicList<word>& faceZoneNames,
1141 List<DynamicList<label> >& fzFaces,
1142 List<DynamicList<bool> >& fzFlips,
1144 DynamicList<word>& cellZoneNames,
1145 List<DynamicList<label> >& czCells
1148 labelList from1ToAllPZones;
1161 labelList from1ToAllFZones;
1175 labelList from1ToAllCZones;
1189 void Foam::polyMeshAdder::addZones
1191 const DynamicList<word>& pointZoneNames,
1192 const List<DynamicList<label> >& pzPoints,
1194 const DynamicList<word>& faceZoneNames,
1195 const List<DynamicList<label> >& fzFaces,
1196 const List<DynamicList<bool> >& fzFlips,
1198 const DynamicList<word>& cellZoneNames,
1199 const List<DynamicList<label> >& czCells,
1204 List<pointZone*> pZones(pzPoints.size());
1207 pZones[i] = new pointZone
1216 List<faceZone*> fZones(fzFaces.size());
1219 fZones[i] = new faceZone
1229 List<cellZone*> cZones(czCells.size());
1232 cZones[i] = new cellZone
1251 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1253 // Returns new mesh and sets
1254 // - map from new cell/face/point/patch to either mesh0 or mesh1
1256 // mesh0Faces/mesh1Faces: corresponding faces on both meshes.
1257 Foam::autoPtr<Foam::polyMesh> Foam::polyMeshAdder::add
1260 const polyMesh& mesh0,
1261 const polyMesh& mesh1,
1262 const faceCoupleInfo& coupleInfo,
1263 autoPtr<mapAddedPolyMesh>& mapPtr
1266 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1267 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1270 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1271 DynamicList<word> allPatchTypes(allPatchNames.size());
1274 labelList from1ToAllPatches(patches1.size());
1275 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1289 pointField allPoints;
1291 // Map from mesh0/1 points to allPoints.
1292 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1293 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1297 label nInternalFaces;
1301 labelList allNeighbour;
1305 labelList nFaces(allPatchNames.size(), 0);
1308 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1309 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1312 labelList from1ToAllCells(mesh1.nCells(), -1);
1320 allPatchNames.size(),
1344 DynamicList<word> pointZoneNames;
1345 List<DynamicList<label> > pzPoints;
1347 DynamicList<word> faceZoneNames;
1348 List<DynamicList<label> > fzFaces;
1349 List<DynamicList<bool> > fzFlips;
1351 DynamicList<word> cellZoneNames;
1352 List<DynamicList<label> > czCells;
1381 // Map from 0 to all patches (since gets compacted)
1382 labelList from0ToAllPatches(patches0.size(), -1);
1384 List<polyPatch*> allPatches
1390 patches0, // Should be boundaryMesh() on new mesh.
1391 allPatchNames.size(),
1393 mesh0.nInternalFaces()
1394 + mesh1.nInternalFaces()
1395 + coupleInfo.cutFaces().size(),
1409 new mapAddedPolyMesh
1421 identity(mesh0.nCells()),
1429 getPatchSizes(patches0),
1430 getPatchStarts(patches0)
1436 // Now we have extracted all information from all meshes.
1437 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1440 autoPtr<polyMesh> tmesh
1445 xferMove(allPoints),
1448 xferMove(allNeighbour)
1451 polyMesh& mesh = tmesh();
1453 // Add zones to new mesh.
1468 // Add patches to new mesh
1469 mesh.addPatches(allPatches);
1475 // Inplace add mesh1 to mesh0
1476 Foam::autoPtr<Foam::mapAddedPolyMesh> Foam::polyMeshAdder::add
1479 const polyMesh& mesh1,
1480 const faceCoupleInfo& coupleInfo,
1481 const bool validBoundary
1484 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1485 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1487 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1488 DynamicList<word> allPatchTypes(allPatchNames.size());
1491 labelList from1ToAllPatches(patches1.size());
1492 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1506 pointField allPoints;
1508 // Map from mesh0/1 points to allPoints.
1509 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1510 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1515 labelList allNeighbour;
1516 label nInternalFaces;
1518 labelList nFaces(allPatchNames.size(), 0);
1522 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1523 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1525 labelList from1ToAllCells(mesh1.nCells(), -1);
1533 allPatchNames.size(),
1557 DynamicList<word> pointZoneNames;
1558 List<DynamicList<label> > pzPoints;
1560 DynamicList<word> faceZoneNames;
1561 List<DynamicList<label> > fzFaces;
1562 List<DynamicList<bool> > fzFlips;
1564 DynamicList<word> cellZoneNames;
1565 List<DynamicList<label> > czCells;
1595 // Store mesh0 patch info before modifying patches0.
1596 labelList mesh0PatchSizes(getPatchSizes(patches0));
1597 labelList mesh0PatchStarts(getPatchStarts(patches0));
1599 // Map from 0 to all patches (since gets compacted)
1600 labelList from0ToAllPatches(patches0.size(), -1);
1602 // Inplace extend mesh0 patches (note that patches0.size() now also
1604 polyBoundaryMesh& allPatches =
1605 const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
1606 allPatches.setSize(allPatchNames.size());
1608 label startFaceI = nInternalFaces;
1610 // Copy patches0 with new sizes. First patches always come from
1611 // mesh0 and will always be present.
1612 label allPatchI = 0;
1614 forAll(from0ToAllPatches, patch0)
1616 // Originates from mesh0. Clone with new size & filter out empty
1619 if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
1621 //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
1623 from0ToAllPatches[patch0] = -1;
1624 // Check if patch was also in mesh1 and update its addressing if so.
1625 if (fromAllTo1Patches[patch0] != -1)
1627 from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1636 allPatches[patch0].clone
1645 // Record new index in allPatches
1646 from0ToAllPatches[patch0] = allPatchI;
1648 // Check if patch was also in mesh1 and update its addressing if so.
1649 if (fromAllTo1Patches[patch0] != -1)
1651 from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchI;
1654 startFaceI += nFaces[patch0];
1660 // Copy unique patches of mesh1.
1661 forAll(from1ToAllPatches, patch1)
1663 label uncompactAllPatchI = from1ToAllPatches[patch1];
1665 if (uncompactAllPatchI >= from0ToAllPatches.size())
1667 // Patch has not been merged with any mesh0 patch.
1671 nFaces[uncompactAllPatchI] == 0
1672 && isA<processorPolyPatch>(patches1[patch1])
1675 //Pout<< "Removing zero sized mesh1 patch "
1676 // << allPatchNames[uncompactAllPatchI] << endl;
1677 from1ToAllPatches[patch1] = -1;
1685 patches1[patch1].clone
1689 nFaces[uncompactAllPatchI],
1694 // Record new index in allPatches
1695 from1ToAllPatches[patch1] = allPatchI;
1697 startFaceI += nFaces[uncompactAllPatchI];
1704 allPatches.setSize(allPatchI);
1707 // Construct map information before changing mesh0 primitives
1708 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1710 autoPtr<mapAddedPolyMesh> mapPtr
1712 new mapAddedPolyMesh
1724 identity(mesh0.nCells()),
1740 // Now we have extracted all information from all meshes.
1741 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1743 labelList patchSizes(getPatchSizes(allPatches));
1744 labelList patchStarts(getPatchStarts(allPatches));
1746 mesh0.resetMotion(); // delete any oldPoints.
1747 mesh0.resetPrimitives
1749 xferMove(allPoints),
1752 xferMove(allNeighbour),
1754 patchStarts, // patchstarts
1755 validBoundary // boundary valid?
1758 // Add zones to new mesh.
1759 mesh0.pointZones().clear();
1760 mesh0.faceZones().clear();
1761 mesh0.cellZones().clear();
1780 Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
1782 const polyMesh& mesh,
1783 const scalar mergeDist
1786 const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
1787 const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
1789 // Because of adding the missing pieces e.g. when redistributing a mesh
1790 // it can be that there are multiple points on the same processor that
1791 // refer to the same shared point.
1793 // Invert point-to-shared addressing
1794 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1796 Map<labelList> sharedToMesh(sharedPointLabels.size());
1798 label nMultiple = 0;
1800 forAll(sharedPointLabels, i)
1802 label pointI = sharedPointLabels[i];
1804 label sharedI = sharedPointAddr[i];
1806 Map<labelList>::iterator iter = sharedToMesh.find(sharedI);
1808 if (iter != sharedToMesh.end())
1810 // sharedI already used by other point. Add this one.
1814 labelList& connectedPointLabels = iter();
1816 label sz = connectedPointLabels.size();
1818 // Check just to make sure.
1819 if (findIndex(connectedPointLabels, pointI) != -1)
1821 FatalErrorIn("polyMeshAdder::findSharedPoints(..)")
1822 << "Duplicate point in sharedPoint addressing." << endl
1823 << "When trying to add point " << pointI << " on shared "
1824 << sharedI << " with connected points "
1825 << connectedPointLabels
1826 << abort(FatalError);
1829 connectedPointLabels.setSize(sz+1);
1830 connectedPointLabels[sz] = pointI;
1834 sharedToMesh.insert(sharedI, labelList(1, pointI));
1839 // Assign single master for every shared with multiple geometric points
1840 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1842 Map<label> pointToMaster(nMultiple);
1844 forAllConstIter(Map<labelList>, sharedToMesh, iter)
1846 const labelList& connectedPointLabels = iter();
1848 //Pout<< "For shared:" << iter.key()
1849 // << " found points:" << connectedPointLabels
1851 // << pointField(mesh.points(), connectedPointLabels) << endl;
1853 if (connectedPointLabels.size() > 1)
1855 const pointField connectedPoints
1858 connectedPointLabels
1861 labelList toMergedPoints;
1862 pointField mergedPoints;
1863 bool hasMerged = Foam::mergePoints
1874 // Invert toMergedPoints
1875 const labelListList mergeSets
1879 mergedPoints.size(),
1884 // Find master for valid merges
1885 forAll(mergeSets, setI)
1887 const labelList& mergeSet = mergeSets[setI];
1889 if (mergeSet.size() > 1)
1891 // Pick lowest numbered point
1892 label masterPointI = labelMax;
1896 label pointI = connectedPointLabels[mergeSet[i]];
1898 masterPointI = min(masterPointI, pointI);
1903 label pointI = connectedPointLabels[mergeSet[i]];
1905 //Pout<< "Merging point " << pointI
1906 // << " at " << mesh.points()[pointI]
1907 // << " into master point "
1909 // << " at " << mesh.points()[masterPointI]
1912 pointToMaster.insert(pointI, masterPointI);
1920 //- Old: geometric merging. Causes problems for two close shared points.
1921 //labelList sharedToMerged;
1922 //pointField mergedPoints;
1923 //bool hasMerged = Foam::mergePoints
1928 // sharedPointLabels
1936 //// Find out which sets of points get merged and create a map from
1937 //// mesh point to unique point.
1939 //Map<label> pointToMaster(10*sharedToMerged.size());
1943 // labelListList mergeSets
1947 // sharedToMerged.size(),
1952 // label nMergeSets = 0;
1954 // forAll(mergeSets, setI)
1956 // const labelList& mergeSet = mergeSets[setI];
1958 // if (mergeSet.size() > 1)
1960 // // Take as master the shared point with the lowest mesh
1961 // // point label. (rather arbitrarily - could use max or
1962 // // any other one of the points)
1966 // label masterI = labelMax;
1968 // forAll(mergeSet, i)
1970 // label sharedI = mergeSet[i];
1972 // masterI = min(masterI, sharedPointLabels[sharedI]);
1975 // forAll(mergeSet, i)
1977 // label sharedI = mergeSet[i];
1979 // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
1986 // // Pout<< "polyMeshAdder : merging:"
1987 // // << pointToMaster.size() << " into " << nMergeSets
1988 // // << " sets." << endl;
1992 return pointToMaster;
1996 void Foam::polyMeshAdder::mergePoints
1998 const polyMesh& mesh,
1999 const Map<label>& pointToMaster,
2000 polyTopoChange& meshMod
2003 // Remove all non-master points.
2004 forAll(mesh.points(), pointI)
2006 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2008 if (iter != pointToMaster.end())
2010 if (iter() != pointI)
2012 meshMod.removePoint(pointI, iter());
2017 // Modify faces for points. Note: could use pointFaces here but want to
2018 // avoid addressing calculation.
2019 const faceList& faces = mesh.faces();
2021 forAll(faces, faceI)
2023 const face& f = faces[faceI];
2025 bool hasMerged = false;
2029 label pointI = f[fp];
2031 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2033 if (iter != pointToMaster.end())
2035 if (iter() != pointI)
2049 label pointI = f[fp];
2051 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2053 if (iter != pointToMaster.end())
2059 label patchID = mesh.boundaryMesh().whichPatch(faceI);
2060 label nei = (patchID == -1 ? mesh.faceNeighbour()[faceI] : -1);
2061 label zoneID = mesh.faceZones().whichZone(faceI);
2062 bool zoneFlip = false;
2066 const faceZone& fZone = mesh.faceZones()[zoneID];
2067 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
2074 newF, // modified face
2075 faceI, // label of face
2076 mesh.faceOwner()[faceI], // owner
2079 patchID, // patch for face
2080 false, // remove from zone
2081 zoneID, // zone for face
2082 zoneFlip // face flip in zone
2090 // ************************************************************************* //