1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*----------------------------------------------------------------------------*/
27 #include "polyMeshAdder.H"
28 #include "mapAddedPolyMesh.H"
30 #include "faceCoupleInfo.H"
31 #include "processorPolyPatch.H"
32 #include "SortableList.H"
34 #include "globalMeshData.H"
35 #include "mergePoints.H"
36 #include "polyModifyFace.H"
37 #include "polyRemovePoint.H"
38 #include "polyTopoChange.H"
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 //- Append all mapped elements of a list to a DynamicList
43 void Foam::polyMeshAdder::append
47 DynamicList<label>& dynLst
50 dynLst.setSize(dynLst.size() + lst.size());
54 label newElem = map[lst[i]];
58 dynLst.append(newElem);
64 //- Append all mapped elements of a list to a DynamicList
65 void Foam::polyMeshAdder::append
69 const SortableList<label>& sortedLst,
70 DynamicList<label>& dynLst
73 dynLst.setSize(dynLst.size() + lst.size());
77 label newElem = map[lst[i]];
79 if (newElem != -1 && findSortedIndex(sortedLst, newElem) == -1)
81 dynLst.append(newElem);
87 // Get index of patch in new set of patchnames/types
88 Foam::label Foam::polyMeshAdder::patchIndex
91 DynamicList<word>& allPatchNames,
92 DynamicList<word>& allPatchTypes
95 // Find the patch name on the list. If the patch is already there
96 // and patch types match, return index
97 const word& pType = p.type();
98 const word& pName = p.name();
100 label patchI = findIndex(allPatchNames, pName);
104 // Patch not found. Append to the list
105 allPatchNames.append(pName);
106 allPatchTypes.append(pType);
108 return allPatchNames.size() - 1;
110 else if (allPatchTypes[patchI] == pType)
112 // Found name and types match
117 // Found the name, but type is different
119 // Duplicate name is not allowed. Create a composite name from the
120 // patch name and case name
121 const word& caseName = p.boundaryMesh().mesh().time().caseName();
123 allPatchNames.append(pName + "_" + caseName);
124 allPatchTypes.append(pType);
126 Pout<< "label patchIndex(const polyPatch& p) : "
127 << "Patch " << p.index() << " named "
128 << pName << " in mesh " << caseName
129 << " already exists, but patch types"
130 << " do not match.\nCreating a composite name as "
131 << allPatchNames[allPatchNames.size() - 1] << endl;
133 return allPatchNames.size() - 1;
138 // Get index of zone in new set of zone names
139 Foam::label Foam::polyMeshAdder::zoneIndex
142 DynamicList<word>& names
145 label zoneI = findIndex(names, curName);
153 // Not found. Add new name to the list
154 names.append(curName);
156 return names.size() - 1;
161 void Foam::polyMeshAdder::mergePatchNames
163 const polyBoundaryMesh& patches0,
164 const polyBoundaryMesh& patches1,
166 DynamicList<word>& allPatchNames,
167 DynamicList<word>& allPatchTypes,
169 labelList& from1ToAllPatches,
170 labelList& fromAllTo1Patches
173 // Insert the mesh0 patches and zones
174 append(patches0.names(), allPatchNames);
175 append(patches0.types(), allPatchTypes);
180 // Patches from 0 are taken over as is; those from 1 get either merged
181 // (if they share name and type) or appended.
182 // Empty patches are filtered out much much later on.
184 // Add mesh1 patches and build map both ways.
185 from1ToAllPatches.setSize(patches1.size());
187 forAll(patches1, patchI)
189 from1ToAllPatches[patchI] = patchIndex
196 allPatchTypes.shrink();
197 allPatchNames.shrink();
199 // Invert 1 to all patch map
200 fromAllTo1Patches.setSize(allPatchNames.size());
201 fromAllTo1Patches = -1;
203 forAll(from1ToAllPatches, i)
205 fromAllTo1Patches[from1ToAllPatches[i]] = i;
210 Foam::labelList Foam::polyMeshAdder::getPatchStarts
212 const polyBoundaryMesh& patches
215 labelList patchStarts(patches.size());
216 forAll(patches, patchI)
218 patchStarts[patchI] = patches[patchI].start();
224 Foam::labelList Foam::polyMeshAdder::getPatchSizes
226 const polyBoundaryMesh& patches
229 labelList patchSizes(patches.size());
230 forAll(patches, patchI)
232 patchSizes[patchI] = patches[patchI].size();
238 Foam::List<Foam::polyPatch*> Foam::polyMeshAdder::combinePatches
240 const polyMesh& mesh0,
241 const polyMesh& mesh1,
242 const polyBoundaryMesh& allBoundaryMesh,
243 const label nAllPatches,
244 const labelList& fromAllTo1Patches,
246 const label nInternalFaces,
247 const labelList& nFaces,
249 labelList& from0ToAllPatches,
250 labelList& from1ToAllPatches
253 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
254 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
257 // Compacted new patch list.
258 DynamicList<polyPatch*> allPatches(nAllPatches);
261 // Map from 0 to all patches (since gets compacted)
262 from0ToAllPatches.setSize(patches0.size());
263 from0ToAllPatches = -1;
265 label startFaceI = nInternalFaces;
267 // Copy patches0 with new sizes. First patches always come from
268 // mesh0 and will always be present.
269 for (label patchI = 0; patchI < patches0.size(); patchI++)
271 // Originates from mesh0. Clone with new size & filter out empty
273 label filteredPatchI;
275 if (nFaces[patchI] == 0 && isA<processorPolyPatch>(patches0[patchI]))
277 //Pout<< "Removing zero sized mesh0 patch "
278 // << patches0[patchI].name() << endl;
283 filteredPatchI = allPatches.size();
287 patches0[patchI].clone
295 startFaceI += nFaces[patchI];
298 // Record new index in allPatches
299 from0ToAllPatches[patchI] = filteredPatchI;
301 // Check if patch was also in mesh1 and update its addressing if so.
302 if (fromAllTo1Patches[patchI] != -1)
304 from1ToAllPatches[fromAllTo1Patches[patchI]] = filteredPatchI;
308 // Copy unique patches of mesh1.
309 forAll(from1ToAllPatches, patchI)
311 label allPatchI = from1ToAllPatches[patchI];
313 if (allPatchI >= patches0.size())
315 // Patch has not been merged with any mesh0 patch.
317 label filteredPatchI;
321 nFaces[allPatchI] == 0
322 && isA<processorPolyPatch>(patches1[patchI])
325 //Pout<< "Removing zero sized mesh1 patch "
326 // << patches1[patchI].name() << endl;
331 filteredPatchI = allPatches.size();
335 patches1[patchI].clone
343 startFaceI += nFaces[allPatchI];
346 from1ToAllPatches[patchI] = filteredPatchI;
356 Foam::labelList Foam::polyMeshAdder::getFaceOrder
358 const cellList& cells,
359 const label nInternalFaces,
360 const labelList& owner,
361 const labelList& neighbour
364 labelList oldToNew(owner.size(), -1);
366 // Leave boundary faces in order
367 for (label faceI = nInternalFaces; faceI < owner.size(); faceI++)
369 oldToNew[faceI] = faceI;
372 // First unassigned face
377 const labelList& cFaces = cells[cellI];
379 SortableList<label> nbr(cFaces.size());
383 label faceI = cFaces[i];
385 label nbrCellI = neighbour[faceI];
389 // Internal face. Get cell on other side.
390 if (nbrCellI == cellI)
392 nbrCellI = owner[faceI];
395 if (cellI < nbrCellI)
402 // nbrCell is master. Let it handle this face.
408 // External face. Do later.
419 oldToNew[cFaces[nbr.indices()[i]]] = newFaceI++;
425 // Check done all faces.
426 forAll(oldToNew, faceI)
428 if (oldToNew[faceI] == -1)
432 "polyMeshAdder::getFaceOrder"
433 "(const cellList&, const label, const labelList&"
434 ", const labelList&) const"
435 ) << "Did not determine new position"
436 << " for face " << faceI
437 << abort(FatalError);
445 // Extends face f with split points. cutEdgeToPoints gives for every
446 // edge the points introduced inbetween the endpoints.
447 void Foam::polyMeshAdder::insertVertices
449 const edgeLookup& cutEdgeToPoints,
450 const Map<label>& meshToMaster,
451 const labelList& masterToCutPoints,
454 DynamicList<label>& workFace,
460 // Check any edge for being cut (check on the cut so takes account
461 // for any point merging on the cut)
465 label v0 = masterF[fp];
466 label v1 = masterF.nextLabel(fp);
468 // Copy existing face point
469 workFace.append(allF[fp]);
471 // See if any edge between v0,v1
473 Map<label>::const_iterator v0Fnd = meshToMaster.find(v0);
474 if (v0Fnd != meshToMaster.end())
476 Map<label>::const_iterator v1Fnd = meshToMaster.find(v1);
477 if (v1Fnd != meshToMaster.end())
479 // Get edge in cutPoint numbering
482 masterToCutPoints[v0Fnd()],
483 masterToCutPoints[v1Fnd()]
486 edgeLookup::const_iterator iter = cutEdgeToPoints.find(cutEdge);
488 if (iter != cutEdgeToPoints.end())
490 const edge& e = iter.key();
491 const labelList& addedPoints = iter();
493 // cutPoints first in allPoints so no need for renumbering
494 if (e[0] == cutEdge[0])
496 forAll(addedPoints, i)
498 workFace.append(addedPoints[i]);
503 forAllReverse(addedPoints, i)
505 workFace.append(addedPoints[i]);
513 if (workFace.size() != allF.size())
516 allF.transfer(workFace);
521 // Adds primitives (cells, faces, points)
526 // - all uncoupled of mesh0
527 // - all coupled faces
528 // - all uncoupled of mesh1
531 // - all uncoupled of mesh0
532 // - all uncoupled of mesh1
533 void Foam::polyMeshAdder::mergePrimitives
535 const polyMesh& mesh0,
536 const polyMesh& mesh1,
537 const faceCoupleInfo& coupleInfo,
539 const label nAllPatches, // number of patches in the new mesh
540 const labelList& fromAllTo1Patches,
541 const labelList& from1ToAllPatches,
543 pointField& allPoints,
544 labelList& from0ToAllPoints,
545 labelList& from1ToAllPoints,
549 labelList& allNeighbour,
550 label& nInternalFaces,
551 labelList& nFacesPerPatch,
554 labelList& from0ToAllFaces,
555 labelList& from1ToAllFaces,
556 labelList& from1ToAllCells
559 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
560 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
562 const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
563 const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
564 const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
570 // Storage for new points
571 allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
574 from0ToAllPoints.setSize(mesh0.nPoints());
575 from0ToAllPoints = -1;
576 from1ToAllPoints.setSize(mesh1.nPoints());
577 from1ToAllPoints = -1;
579 // Copy coupled points (on cut)
581 const pointField& cutPoints = coupleInfo.cutPoints();
583 //const labelListList& cutToMasterPoints =
584 // coupleInfo.cutToMasterPoints();
585 labelListList cutToMasterPoints
590 coupleInfo.masterToCutPoints()
594 //const labelListList& cutToSlavePoints =
595 // coupleInfo.cutToSlavePoints();
596 labelListList cutToSlavePoints
601 coupleInfo.slaveToCutPoints()
607 allPoints[allPointI] = cutPoints[i];
609 // Mark all master and slave points referring to this point.
611 const labelList& masterPoints = cutToMasterPoints[i];
613 forAll(masterPoints, j)
615 label mesh0PointI = masterPatch.meshPoints()[masterPoints[j]];
616 from0ToAllPoints[mesh0PointI] = allPointI;
619 const labelList& slavePoints = cutToSlavePoints[i];
621 forAll(slavePoints, j)
623 label mesh1PointI = slavePatch.meshPoints()[slavePoints[j]];
624 from1ToAllPoints[mesh1PointI] = allPointI;
630 // Add uncoupled mesh0 points
631 forAll(mesh0.points(), pointI)
633 if (from0ToAllPoints[pointI] == -1)
635 allPoints[allPointI] = mesh0.points()[pointI];
636 from0ToAllPoints[pointI] = allPointI;
641 // Add uncoupled mesh1 points
642 forAll(mesh1.points(), pointI)
644 if (from1ToAllPoints[pointI] == -1)
646 allPoints[allPointI] = mesh1.points()[pointI];
647 from1ToAllPoints[pointI] = allPointI;
652 allPoints.setSize(allPointI);
659 nFacesPerPatch.setSize(nAllPatches);
662 // Storage for faces and owner/neighbour
663 allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
664 allOwner.setSize(allFaces.size());
666 allNeighbour.setSize(allFaces.size());
670 from0ToAllFaces.setSize(mesh0.nFaces());
671 from0ToAllFaces = -1;
672 from1ToAllFaces.setSize(mesh1.nFaces());
673 from1ToAllFaces = -1;
675 // Copy mesh0 internal faces (always uncoupled)
676 for (label faceI = 0; faceI < mesh0.nInternalFaces(); faceI++)
678 allFaces[allFaceI] = renumber(from0ToAllPoints, mesh0.faces()[faceI]);
679 allOwner[allFaceI] = mesh0.faceOwner()[faceI];
680 allNeighbour[allFaceI] = mesh0.faceNeighbour()[faceI];
681 from0ToAllFaces[faceI] = allFaceI++;
684 // Copy coupled faces. Every coupled face has an equivalent master and
685 // slave. Also uncount as boundary faces all the newly coupled faces.
686 const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
687 const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
691 label masterFaceI = cutToMasterFaces[i];
693 label mesh0FaceI = masterPatch.addressing()[masterFaceI];
695 if (from0ToAllFaces[mesh0FaceI] == -1)
697 // First occurrence of face
698 from0ToAllFaces[mesh0FaceI] = allFaceI;
700 // External face becomes internal so uncount
701 label patch0 = patches0.whichPatch(mesh0FaceI);
702 nFacesPerPatch[patch0]--;
705 label slaveFaceI = cutToSlaveFaces[i];
707 label mesh1FaceI = slavePatch.addressing()[slaveFaceI];
709 if (from1ToAllFaces[mesh1FaceI] == -1)
711 from1ToAllFaces[mesh1FaceI] = allFaceI;
713 label patch1 = patches1.whichPatch(mesh1FaceI);
714 nFacesPerPatch[from1ToAllPatches[patch1]]--;
717 // Copy cut face (since cutPoints are copied first no renumbering
719 allFaces[allFaceI] = cutFaces[i];
720 allOwner[allFaceI] = mesh0.faceOwner()[mesh0FaceI];
721 allNeighbour[allFaceI] = mesh1.faceOwner()[mesh1FaceI] + mesh0.nCells();
726 // Copy mesh1 internal faces (always uncoupled)
727 for (label faceI = 0; faceI < mesh1.nInternalFaces(); faceI++)
729 allFaces[allFaceI] = renumber(from1ToAllPoints, mesh1.faces()[faceI]);
730 allOwner[allFaceI] = mesh1.faceOwner()[faceI] + mesh0.nCells();
731 allNeighbour[allFaceI] = mesh1.faceNeighbour()[faceI] + mesh0.nCells();
732 from1ToAllFaces[faceI] = allFaceI++;
735 nInternalFaces = allFaceI;
737 // Copy (unmarked/uncoupled) external faces in new order.
738 for (label allPatchI = 0; allPatchI < nAllPatches; allPatchI++)
740 if (allPatchI < patches0.size())
742 // Patch is present in mesh0
743 const polyPatch& pp = patches0[allPatchI];
745 nFacesPerPatch[allPatchI] += pp.size();
747 label faceI = pp.start();
751 if (from0ToAllFaces[faceI] == -1)
753 // Is uncoupled face since has not yet been dealt with
754 allFaces[allFaceI] = renumber
759 allOwner[allFaceI] = mesh0.faceOwner()[faceI];
760 allNeighbour[allFaceI] = -1;
762 from0ToAllFaces[faceI] = allFaceI++;
767 if (fromAllTo1Patches[allPatchI] != -1)
769 // Patch is present in mesh1
770 const polyPatch& pp = patches1[fromAllTo1Patches[allPatchI]];
772 nFacesPerPatch[allPatchI] += pp.size();
774 label faceI = pp.start();
778 if (from1ToAllFaces[faceI] == -1)
781 allFaces[allFaceI] = renumber
787 mesh1.faceOwner()[faceI]
789 allNeighbour[allFaceI] = -1;
791 from1ToAllFaces[faceI] = allFaceI++;
797 allFaces.setSize(allFaceI);
798 allOwner.setSize(allFaceI);
799 allNeighbour.setSize(allFaceI);
802 // So now we have all ok for one-to-one mapping.
803 // For split slace faces:
804 // - mesh consistent with slave side
805 // - mesh not consistent with owner side. It is not zipped up, the
806 // original faces need edges split.
808 // Use brute force to prevent having to calculate addressing:
809 // - get map from master edge to split edges.
810 // - check all faces to find any edge that is split.
812 // From two cut-points to labels of cut-points inbetween.
813 // (in order: from e[0] to e[1]
814 const edgeLookup& cutEdgeToPoints = coupleInfo.cutEdgeToPoints();
816 // Get map of master face (in mesh labels) that are in cut. These faces
817 // do not need to be renumbered.
818 labelHashSet masterCutFaces(cutToMasterFaces.size());
819 forAll(cutToMasterFaces, i)
821 label meshFaceI = masterPatch.addressing()[cutToMasterFaces[i]];
823 masterCutFaces.insert(meshFaceI);
826 DynamicList<label> workFace(100);
828 forAll(from0ToAllFaces, face0)
830 if (!masterCutFaces.found(face0))
832 label allFaceI = from0ToAllFaces[face0];
837 masterPatch.meshPointMap(),
838 coupleInfo.masterToCutPoints(),
839 mesh0.faces()[face0],
847 // Same for slave face
849 labelHashSet slaveCutFaces(cutToSlaveFaces.size());
850 forAll(cutToSlaveFaces, i)
852 label meshFaceI = slavePatch.addressing()[cutToSlaveFaces[i]];
854 slaveCutFaces.insert(meshFaceI);
857 forAll(from1ToAllFaces, face1)
859 if (!slaveCutFaces.found(face1))
861 label allFaceI = from1ToAllFaces[face1];
866 slavePatch.meshPointMap(),
867 coupleInfo.slaveToCutPoints(),
868 mesh1.faces()[face1],
877 // Now we have a full facelist and owner/neighbour addressing.
883 from1ToAllCells.setSize(mesh1.nCells());
884 from1ToAllCells = -1;
886 forAll(mesh1.cells(), i)
888 from1ToAllCells[i] = i + mesh0.nCells();
891 // Make cells (= cell-face addressing)
892 nCells = mesh0.nCells() + mesh1.nCells();
893 cellList allCells(nCells);
894 primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
896 // Reorder faces for upper-triangular order.
908 inplaceReorder(oldToNew, allFaces);
909 inplaceReorder(oldToNew, allOwner);
910 inplaceReorder(oldToNew, allNeighbour);
911 inplaceRenumber(oldToNew, from0ToAllFaces);
912 inplaceRenumber(oldToNew, from1ToAllFaces);
916 void Foam::polyMeshAdder::mergePointZones
918 const pointZoneMesh& pz0,
919 const pointZoneMesh& pz1,
920 const labelList& from0ToAllPoints,
921 const labelList& from1ToAllPoints,
923 DynamicList<word>& zoneNames,
924 labelList& from1ToAll,
925 List<DynamicList<label> >& pzPoints
928 zoneNames.setSize(pz0.size() + pz1.size());
931 append(pz0.names(), zoneNames);
933 from1ToAll.setSize(pz1.size());
937 from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
941 // Point labels per merged zone
942 pzPoints.setSize(zoneNames.size());
946 append(from0ToAllPoints, pz0[zoneI], pzPoints[zoneI]);
949 // Get sorted zone contents for duplicate element recognition
950 PtrList<SortableList<label> > pzPointsSorted(pzPoints.size());
951 forAll(pzPoints, zoneI)
956 new SortableList<label>(pzPoints[zoneI].shrink())
960 // Now we have full addressing for points so do the pointZones of mesh1.
963 // Relabel all points of zone and add to correct pzPoints.
964 label allZoneI = from1ToAll[zoneI];
970 pzPointsSorted[allZoneI],
977 pzPoints[i].shrink();
982 void Foam::polyMeshAdder::mergeFaceZones
984 const faceZoneMesh& fz0,
985 const faceZoneMesh& fz1,
986 const labelList& from0ToAllFaces,
987 const labelList& from1ToAllFaces,
989 DynamicList<word>& zoneNames,
990 labelList& from1ToAll,
991 List<DynamicList<label> >& fzFaces,
992 List<DynamicList<bool> >& fzFlips
995 zoneNames.setSize(fz0.size() + fz1.size());
997 append(fz0.names(), zoneNames);
999 from1ToAll.setSize(fz1.size());
1003 from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
1008 // Create temporary lists for faceZones.
1009 fzFaces.setSize(zoneNames.size());
1010 fzFlips.setSize(zoneNames.size());
1013 DynamicList<label>& newZone = fzFaces[zoneI];
1014 DynamicList<bool>& newFlip = fzFlips[zoneI];
1016 newZone.setSize(fz0[zoneI].size());
1017 newFlip.setSize(newZone.size());
1019 const labelList& addressing = fz0[zoneI];
1020 const boolList& flipMap = fz0[zoneI].flipMap();
1022 forAll(addressing, i)
1024 label faceI = addressing[i];
1026 if (from0ToAllFaces[faceI] != -1)
1028 newZone.append(from0ToAllFaces[faceI]);
1029 newFlip.append(flipMap[i]);
1034 // Get sorted zone contents for duplicate element recognition
1035 PtrList<SortableList<label> > fzFacesSorted(fzFaces.size());
1036 forAll(fzFaces, zoneI)
1041 new SortableList<label>(fzFaces[zoneI].shrink())
1045 // Now we have full addressing for faces so do the faceZones of mesh1.
1048 label allZoneI = from1ToAll[zoneI];
1049 DynamicList<label>& newZone = fzFaces[allZoneI];
1050 const SortableList<label>& newZoneSorted = fzFacesSorted[allZoneI];
1051 DynamicList<bool>& newFlip = fzFlips[allZoneI];
1053 newZone.setSize(newZone.size() + fz1[zoneI].size());
1054 newFlip.setSize(newZone.size());
1056 const labelList& addressing = fz1[zoneI];
1057 const boolList& flipMap = fz1[zoneI].flipMap();
1059 forAll(addressing, i)
1061 label faceI = addressing[i];
1062 label allFaceI = from1ToAllFaces[faceI];
1067 && findSortedIndex(newZoneSorted, allFaceI) == -1
1070 newZone.append(allFaceI);
1071 newFlip.append(flipMap[i]);
1078 fzFaces[i].shrink();
1079 fzFlips[i].shrink();
1084 void Foam::polyMeshAdder::mergeCellZones
1086 const cellZoneMesh& cz0,
1087 const cellZoneMesh& cz1,
1088 const labelList& from1ToAllCells,
1090 DynamicList<word>& zoneNames,
1091 labelList& from1ToAll,
1092 List<DynamicList<label> >& czCells
1095 zoneNames.setSize(cz0.size() + cz1.size());
1097 append(cz0.names(), zoneNames);
1099 from1ToAll.setSize(cz1.size());
1102 from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
1107 // Create temporary lists for cellZones.
1108 czCells.setSize(zoneNames.size());
1111 // Insert mesh0 cells
1112 append(cz0[zoneI], czCells[zoneI]);
1115 // Cell mapping is trivial. Also no duplicate elements possible.
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
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
1759 patchStarts, // patchstarts
1760 validBoundary // boundary valid?
1763 // Add zones to new mesh.
1764 mesh0.pointZones().clear();
1765 mesh0.faceZones().clear();
1766 mesh0.cellZones().clear();
1785 Foam::Map<Foam::label> Foam::polyMeshAdder::findSharedPoints
1787 const polyMesh& mesh,
1788 const scalar mergeDist
1791 const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
1792 const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
1794 // Because of adding the missing pieces e.g. when redistributing a mesh
1795 // it can be that there are multiple points on the same processor that
1796 // refer to the same shared point.
1798 // Invert point-to-shared addressing
1799 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1801 Map<labelList> sharedToMesh(sharedPointLabels.size());
1803 label nMultiple = 0;
1805 forAll(sharedPointLabels, i)
1807 label pointI = sharedPointLabels[i];
1809 label sharedI = sharedPointAddr[i];
1811 Map<labelList>::iterator iter = sharedToMesh.find(sharedI);
1813 if (iter != sharedToMesh.end())
1815 // sharedI already used by other point. Add this one.
1819 labelList& connectedPointLabels = iter();
1821 label sz = connectedPointLabels.size();
1823 // Check just to make sure.
1824 if (findIndex(connectedPointLabels, pointI) != -1)
1826 FatalErrorIn("polyMeshAdder::findSharedPoints(..)")
1827 << "Duplicate point in sharedPoint addressing." << endl
1828 << "When trying to add point " << pointI << " on shared "
1829 << sharedI << " with connected points "
1830 << connectedPointLabels
1831 << abort(FatalError);
1834 connectedPointLabels.setSize(sz+1);
1835 connectedPointLabels[sz] = pointI;
1839 sharedToMesh.insert(sharedI, labelList(1, pointI));
1844 // Assign single master for every shared with multiple geometric points
1845 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1847 Map<label> pointToMaster(nMultiple);
1849 forAllConstIter(Map<labelList>, sharedToMesh, iter)
1851 const labelList& connectedPointLabels = iter();
1853 //Pout<< "For shared:" << iter.key()
1854 // << " found points:" << connectedPointLabels
1856 // << pointField(mesh.points(), connectedPointLabels) << endl;
1858 if (connectedPointLabels.size() > 1)
1860 const pointField connectedPoints
1863 connectedPointLabels
1866 labelList toMergedPoints;
1867 pointField mergedPoints;
1868 bool hasMerged = Foam::mergePoints
1879 // Invert toMergedPoints
1880 const labelListList mergeSets
1884 mergedPoints.size(),
1889 // Find master for valid merges
1890 forAll(mergeSets, setI)
1892 const labelList& mergeSet = mergeSets[setI];
1894 if (mergeSet.size() > 1)
1896 // Pick lowest numbered point
1897 label masterPointI = labelMax;
1901 label pointI = connectedPointLabels[mergeSet[i]];
1903 masterPointI = min(masterPointI, pointI);
1908 label pointI = connectedPointLabels[mergeSet[i]];
1910 //Pout<< "Merging point " << pointI
1911 // << " at " << mesh.points()[pointI]
1912 // << " into master point "
1914 // << " at " << mesh.points()[masterPointI]
1917 pointToMaster.insert(pointI, masterPointI);
1925 //- Old: geometric merging. Causes problems for two close shared points.
1926 //labelList sharedToMerged;
1927 //pointField mergedPoints;
1928 //bool hasMerged = Foam::mergePoints
1932 // IndirectList<point>
1935 // sharedPointLabels
1944 //// Find out which sets of points get merged and create a map from
1945 //// mesh point to unique point.
1947 //Map<label> pointToMaster(10*sharedToMerged.size());
1951 // labelListList mergeSets
1955 // sharedToMerged.size(),
1960 // label nMergeSets = 0;
1962 // forAll(mergeSets, setI)
1964 // const labelList& mergeSet = mergeSets[setI];
1966 // if (mergeSet.size() > 1)
1968 // // Take as master the shared point with the lowest mesh
1969 // // point label. (rather arbitrarily - could use max or
1970 // // any other one of the points)
1974 // label masterI = labelMax;
1976 // forAll(mergeSet, i)
1978 // label sharedI = mergeSet[i];
1980 // masterI = min(masterI, sharedPointLabels[sharedI]);
1983 // forAll(mergeSet, i)
1985 // label sharedI = mergeSet[i];
1987 // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
1994 // // Pout<< "polyMeshAdder : merging:"
1995 // // << pointToMaster.size() << " into " << nMergeSets
1996 // // << " sets." << endl;
2000 return pointToMaster;
2004 void Foam::polyMeshAdder::mergePoints
2006 const polyMesh& mesh,
2007 const Map<label>& pointToMaster,
2008 polyTopoChange& meshMod
2011 // Remove all non-master points.
2012 forAll(mesh.points(), pointI)
2014 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2016 if (iter != pointToMaster.end())
2018 if (iter() != pointI)
2020 //1.4.1: meshMod.removePoint(pointI, iter());
2021 meshMod.setAction(polyRemovePoint(pointI));
2026 // Modify faces for points. Note: could use pointFaces here but want to
2027 // avoid addressing calculation.
2028 const faceList& faces = mesh.faces();
2030 forAll(faces, faceI)
2032 const face& f = faces[faceI];
2034 bool hasMerged = false;
2038 label pointI = f[fp];
2040 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2042 if (iter != pointToMaster.end())
2044 if (iter() != pointI)
2058 label pointI = f[fp];
2060 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2062 if (iter != pointToMaster.end())
2068 label patchID = mesh.boundaryMesh().whichPatch(faceI);
2069 label nei = (patchID == -1 ? mesh.faceNeighbour()[faceI] : -1);
2070 label zoneID = mesh.faceZones().whichZone(faceI);
2071 bool zoneFlip = false;
2075 const faceZone& fZone = mesh.faceZones()[zoneID];
2076 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
2083 newF, // modified face
2084 faceI, // label of face
2085 mesh.faceOwner()[faceI], // owner
2088 patchID, // patch for face
2089 false, // remove from zone
2090 zoneID, // zone for face
2091 zoneFlip // face flip in zone
2099 // ************************************************************************* //