1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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.setCapacity(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())
515 allF.transfer(workFace);
520 // Adds primitives (cells, faces, points)
525 // - all uncoupled of mesh0
526 // - all coupled faces
527 // - all uncoupled of mesh1
530 // - all uncoupled of mesh0
531 // - all uncoupled of mesh1
532 void Foam::polyMeshAdder::mergePrimitives
534 const polyMesh& mesh0,
535 const polyMesh& mesh1,
536 const faceCoupleInfo& coupleInfo,
538 const label nAllPatches, // number of patches in the new mesh
539 const labelList& fromAllTo1Patches,
540 const labelList& from1ToAllPatches,
542 pointField& allPoints,
543 labelList& from0ToAllPoints,
544 labelList& from1ToAllPoints,
548 labelList& allNeighbour,
549 label& nInternalFaces,
550 labelList& nFacesPerPatch,
553 labelList& from0ToAllFaces,
554 labelList& from1ToAllFaces,
555 labelList& from1ToAllCells
558 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
559 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
561 const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
562 const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
563 const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
569 // Storage for new points
570 allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
573 from0ToAllPoints.setSize(mesh0.nPoints());
574 from0ToAllPoints = -1;
575 from1ToAllPoints.setSize(mesh1.nPoints());
576 from1ToAllPoints = -1;
578 // Copy coupled points (on cut)
580 const pointField& cutPoints = coupleInfo.cutPoints();
582 //const labelListList& cutToMasterPoints =
583 // coupleInfo.cutToMasterPoints();
584 labelListList cutToMasterPoints
589 coupleInfo.masterToCutPoints()
593 //const labelListList& cutToSlavePoints =
594 // coupleInfo.cutToSlavePoints();
595 labelListList cutToSlavePoints
600 coupleInfo.slaveToCutPoints()
606 allPoints[allPointI] = cutPoints[i];
608 // Mark all master and slave points referring to this point.
610 const labelList& masterPoints = cutToMasterPoints[i];
612 forAll(masterPoints, j)
614 label mesh0PointI = masterPatch.meshPoints()[masterPoints[j]];
615 from0ToAllPoints[mesh0PointI] = allPointI;
618 const labelList& slavePoints = cutToSlavePoints[i];
620 forAll(slavePoints, j)
622 label mesh1PointI = slavePatch.meshPoints()[slavePoints[j]];
623 from1ToAllPoints[mesh1PointI] = allPointI;
629 // Add uncoupled mesh0 points
630 forAll(mesh0.points(), pointI)
632 if (from0ToAllPoints[pointI] == -1)
634 allPoints[allPointI] = mesh0.points()[pointI];
635 from0ToAllPoints[pointI] = allPointI;
640 // Add uncoupled mesh1 points
641 forAll(mesh1.points(), pointI)
643 if (from1ToAllPoints[pointI] == -1)
645 allPoints[allPointI] = mesh1.points()[pointI];
646 from1ToAllPoints[pointI] = allPointI;
651 allPoints.setSize(allPointI);
658 nFacesPerPatch.setSize(nAllPatches);
661 // Storage for faces and owner/neighbour
662 allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
663 allOwner.setSize(allFaces.size());
665 allNeighbour.setSize(allFaces.size());
669 from0ToAllFaces.setSize(mesh0.nFaces());
670 from0ToAllFaces = -1;
671 from1ToAllFaces.setSize(mesh1.nFaces());
672 from1ToAllFaces = -1;
674 // Copy mesh0 internal faces (always uncoupled)
675 for (label faceI = 0; faceI < mesh0.nInternalFaces(); faceI++)
677 allFaces[allFaceI] = renumber(from0ToAllPoints, mesh0.faces()[faceI]);
678 allOwner[allFaceI] = mesh0.faceOwner()[faceI];
679 allNeighbour[allFaceI] = mesh0.faceNeighbour()[faceI];
680 from0ToAllFaces[faceI] = allFaceI++;
683 // Copy coupled faces. Every coupled face has an equivalent master and
684 // slave. Also uncount as boundary faces all the newly coupled faces.
685 const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
686 const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
690 label masterFaceI = cutToMasterFaces[i];
692 label mesh0FaceI = masterPatch.addressing()[masterFaceI];
694 if (from0ToAllFaces[mesh0FaceI] == -1)
696 // First occurrence of face
697 from0ToAllFaces[mesh0FaceI] = allFaceI;
699 // External face becomes internal so uncount
700 label patch0 = patches0.whichPatch(mesh0FaceI);
701 nFacesPerPatch[patch0]--;
704 label slaveFaceI = cutToSlaveFaces[i];
706 label mesh1FaceI = slavePatch.addressing()[slaveFaceI];
708 if (from1ToAllFaces[mesh1FaceI] == -1)
710 from1ToAllFaces[mesh1FaceI] = allFaceI;
712 label patch1 = patches1.whichPatch(mesh1FaceI);
713 nFacesPerPatch[from1ToAllPatches[patch1]]--;
716 // Copy cut face (since cutPoints are copied first no renumbering
718 allFaces[allFaceI] = cutFaces[i];
719 allOwner[allFaceI] = mesh0.faceOwner()[mesh0FaceI];
720 allNeighbour[allFaceI] = mesh1.faceOwner()[mesh1FaceI] + mesh0.nCells();
725 // Copy mesh1 internal faces (always uncoupled)
726 for (label faceI = 0; faceI < mesh1.nInternalFaces(); faceI++)
728 allFaces[allFaceI] = renumber(from1ToAllPoints, mesh1.faces()[faceI]);
729 allOwner[allFaceI] = mesh1.faceOwner()[faceI] + mesh0.nCells();
730 allNeighbour[allFaceI] = mesh1.faceNeighbour()[faceI] + mesh0.nCells();
731 from1ToAllFaces[faceI] = allFaceI++;
734 nInternalFaces = allFaceI;
736 // Copy (unmarked/uncoupled) external faces in new order.
737 for (label allPatchI = 0; allPatchI < nAllPatches; allPatchI++)
739 if (allPatchI < patches0.size())
741 // Patch is present in mesh0
742 const polyPatch& pp = patches0[allPatchI];
744 nFacesPerPatch[allPatchI] += pp.size();
746 label faceI = pp.start();
750 if (from0ToAllFaces[faceI] == -1)
752 // Is uncoupled face since has not yet been dealt with
753 allFaces[allFaceI] = renumber
758 allOwner[allFaceI] = mesh0.faceOwner()[faceI];
759 allNeighbour[allFaceI] = -1;
761 from0ToAllFaces[faceI] = allFaceI++;
766 if (fromAllTo1Patches[allPatchI] != -1)
768 // Patch is present in mesh1
769 const polyPatch& pp = patches1[fromAllTo1Patches[allPatchI]];
771 nFacesPerPatch[allPatchI] += pp.size();
773 label faceI = pp.start();
777 if (from1ToAllFaces[faceI] == -1)
780 allFaces[allFaceI] = renumber
786 mesh1.faceOwner()[faceI]
788 allNeighbour[allFaceI] = -1;
790 from1ToAllFaces[faceI] = allFaceI++;
796 allFaces.setSize(allFaceI);
797 allOwner.setSize(allFaceI);
798 allNeighbour.setSize(allFaceI);
801 // So now we have all ok for one-to-one mapping.
802 // For split slace faces:
803 // - mesh consistent with slave side
804 // - mesh not consistent with owner side. It is not zipped up, the
805 // original faces need edges split.
807 // Use brute force to prevent having to calculate addressing:
808 // - get map from master edge to split edges.
809 // - check all faces to find any edge that is split.
811 // From two cut-points to labels of cut-points inbetween.
812 // (in order: from e[0] to e[1]
813 const edgeLookup& cutEdgeToPoints = coupleInfo.cutEdgeToPoints();
815 // Get map of master face (in mesh labels) that are in cut. These faces
816 // do not need to be renumbered.
817 labelHashSet masterCutFaces(cutToMasterFaces.size());
818 forAll(cutToMasterFaces, i)
820 label meshFaceI = masterPatch.addressing()[cutToMasterFaces[i]];
822 masterCutFaces.insert(meshFaceI);
825 DynamicList<label> workFace(100);
827 forAll(from0ToAllFaces, face0)
829 if (!masterCutFaces.found(face0))
831 label allFaceI = from0ToAllFaces[face0];
836 masterPatch.meshPointMap(),
837 coupleInfo.masterToCutPoints(),
838 mesh0.faces()[face0],
846 // Same for slave face
848 labelHashSet slaveCutFaces(cutToSlaveFaces.size());
849 forAll(cutToSlaveFaces, i)
851 label meshFaceI = slavePatch.addressing()[cutToSlaveFaces[i]];
853 slaveCutFaces.insert(meshFaceI);
856 forAll(from1ToAllFaces, face1)
858 if (!slaveCutFaces.found(face1))
860 label allFaceI = from1ToAllFaces[face1];
865 slavePatch.meshPointMap(),
866 coupleInfo.slaveToCutPoints(),
867 mesh1.faces()[face1],
876 // Now we have a full facelist and owner/neighbour addressing.
882 from1ToAllCells.setSize(mesh1.nCells());
883 from1ToAllCells = -1;
885 forAll(mesh1.cells(), i)
887 from1ToAllCells[i] = i + mesh0.nCells();
890 // Make cells (= cell-face addressing)
891 nCells = mesh0.nCells() + mesh1.nCells();
892 cellList allCells(nCells);
893 primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
895 // Reorder faces for upper-triangular order.
907 inplaceReorder(oldToNew, allFaces);
908 inplaceReorder(oldToNew, allOwner);
909 inplaceReorder(oldToNew, allNeighbour);
910 inplaceRenumber(oldToNew, from0ToAllFaces);
911 inplaceRenumber(oldToNew, from1ToAllFaces);
915 void Foam::polyMeshAdder::mergePointZones
917 const pointZoneMesh& pz0,
918 const pointZoneMesh& pz1,
919 const labelList& from0ToAllPoints,
920 const labelList& from1ToAllPoints,
922 DynamicList<word>& zoneNames,
923 labelList& from1ToAll,
924 List<DynamicList<label> >& pzPoints
927 zoneNames.setCapacity(pz0.size() + pz1.size());
930 append(pz0.names(), zoneNames);
932 from1ToAll.setSize(pz1.size());
936 from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
940 // Point labels per merged zone
941 pzPoints.setSize(zoneNames.size());
945 append(from0ToAllPoints, pz0[zoneI], pzPoints[zoneI]);
948 // Get sorted zone contents for duplicate element recognition
949 PtrList<SortableList<label> > pzPointsSorted(pzPoints.size());
950 forAll(pzPoints, zoneI)
955 new SortableList<label>(pzPoints[zoneI])
959 // Now we have full addressing for points so do the pointZones of mesh1.
962 // Relabel all points of zone and add to correct pzPoints.
963 label allZoneI = from1ToAll[zoneI];
969 pzPointsSorted[allZoneI],
976 pzPoints[i].shrink();
981 void Foam::polyMeshAdder::mergeFaceZones
983 const faceZoneMesh& fz0,
984 const faceZoneMesh& fz1,
985 const labelList& from0ToAllFaces,
986 const labelList& from1ToAllFaces,
988 DynamicList<word>& zoneNames,
989 labelList& from1ToAll,
990 List<DynamicList<label> >& fzFaces,
991 List<DynamicList<bool> >& fzFlips
994 zoneNames.setCapacity(fz0.size() + fz1.size());
996 append(fz0.names(), zoneNames);
998 from1ToAll.setSize(fz1.size());
1002 from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
1007 // Create temporary lists for faceZones.
1008 fzFaces.setSize(zoneNames.size());
1009 fzFlips.setSize(zoneNames.size());
1012 DynamicList<label>& newZone = fzFaces[zoneI];
1013 DynamicList<bool>& newFlip = fzFlips[zoneI];
1015 newZone.setCapacity(fz0[zoneI].size());
1016 newFlip.setCapacity(newZone.size());
1018 const labelList& addressing = fz0[zoneI];
1019 const boolList& flipMap = fz0[zoneI].flipMap();
1021 forAll(addressing, i)
1023 label faceI = addressing[i];
1025 if (from0ToAllFaces[faceI] != -1)
1027 newZone.append(from0ToAllFaces[faceI]);
1028 newFlip.append(flipMap[i]);
1033 // Get sorted zone contents for duplicate element recognition
1034 PtrList<SortableList<label> > fzFacesSorted(fzFaces.size());
1035 forAll(fzFaces, zoneI)
1040 new SortableList<label>(fzFaces[zoneI])
1044 // Now we have full addressing for faces so do the faceZones of mesh1.
1047 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.setCapacity(newZone.size() + fz1[zoneI].size());
1054 newFlip.setCapacity(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.setCapacity(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]);
1116 // Cell mapping is trivial.
1119 label allZoneI = from1ToAll[zoneI];
1121 append(from1ToAllCells, cz1[zoneI], czCells[allZoneI]);
1126 czCells[i].shrink();
1131 void Foam::polyMeshAdder::mergeZones
1133 const polyMesh& mesh0,
1134 const polyMesh& mesh1,
1135 const labelList& from0ToAllPoints,
1136 const labelList& from0ToAllFaces,
1138 const labelList& from1ToAllPoints,
1139 const labelList& from1ToAllFaces,
1140 const labelList& from1ToAllCells,
1142 DynamicList<word>& pointZoneNames,
1143 List<DynamicList<label> >& pzPoints,
1145 DynamicList<word>& faceZoneNames,
1146 List<DynamicList<label> >& fzFaces,
1147 List<DynamicList<bool> >& fzFlips,
1149 DynamicList<word>& cellZoneNames,
1150 List<DynamicList<label> >& czCells
1153 labelList from1ToAllPZones;
1166 labelList from1ToAllFZones;
1180 labelList from1ToAllCZones;
1194 void Foam::polyMeshAdder::addZones
1196 const DynamicList<word>& pointZoneNames,
1197 const List<DynamicList<label> >& pzPoints,
1199 const DynamicList<word>& faceZoneNames,
1200 const List<DynamicList<label> >& fzFaces,
1201 const List<DynamicList<bool> >& fzFlips,
1203 const DynamicList<word>& cellZoneNames,
1204 const List<DynamicList<label> >& czCells,
1209 List<pointZone*> pZones(pzPoints.size());
1212 pZones[i] = new pointZone
1221 List<faceZone*> fZones(fzFaces.size());
1224 fZones[i] = new faceZone
1234 List<cellZone*> cZones(czCells.size());
1237 cZones[i] = new cellZone
1256 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1258 // Returns new mesh and sets
1259 // - map from new cell/face/point/patch to either mesh0 or mesh1
1261 // mesh0Faces/mesh1Faces: corresponding faces on both meshes.
1262 Foam::autoPtr<Foam::polyMesh> Foam::polyMeshAdder::add
1265 const polyMesh& mesh0,
1266 const polyMesh& mesh1,
1267 const faceCoupleInfo& coupleInfo,
1268 autoPtr<mapAddedPolyMesh>& mapPtr
1271 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1272 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1275 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1276 DynamicList<word> allPatchTypes(allPatchNames.size());
1279 labelList from1ToAllPatches(patches1.size());
1280 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1294 pointField allPoints;
1296 // Map from mesh0/1 points to allPoints.
1297 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1298 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1302 label nInternalFaces;
1306 labelList allNeighbour;
1310 labelList nFaces(allPatchNames.size(), 0);
1313 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1314 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1317 labelList from1ToAllCells(mesh1.nCells(), -1);
1325 allPatchNames.size(),
1349 DynamicList<word> pointZoneNames;
1350 List<DynamicList<label> > pzPoints;
1352 DynamicList<word> faceZoneNames;
1353 List<DynamicList<label> > fzFaces;
1354 List<DynamicList<bool> > fzFlips;
1356 DynamicList<word> cellZoneNames;
1357 List<DynamicList<label> > czCells;
1386 // Map from 0 to all patches (since gets compacted)
1387 labelList from0ToAllPatches(patches0.size(), -1);
1389 List<polyPatch*> allPatches
1395 patches0, // Should be boundaryMesh() on new mesh.
1396 allPatchNames.size(),
1398 mesh0.nInternalFaces()
1399 + mesh1.nInternalFaces()
1400 + coupleInfo.cutFaces().size(),
1414 new mapAddedPolyMesh
1426 identity(mesh0.nCells()),
1434 getPatchSizes(patches0),
1435 getPatchStarts(patches0)
1441 // Now we have extracted all information from all meshes.
1442 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1445 autoPtr<polyMesh> tmesh
1450 xferMove(allPoints),
1453 xferMove(allNeighbour)
1456 polyMesh& mesh = tmesh();
1458 // Add zones to new mesh.
1473 // Add patches to new mesh
1474 mesh.addPatches(allPatches);
1480 // Inplace add mesh1 to mesh0
1481 Foam::autoPtr<Foam::mapAddedPolyMesh> Foam::polyMeshAdder::add
1484 const polyMesh& mesh1,
1485 const faceCoupleInfo& coupleInfo,
1486 const bool validBoundary
1489 const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1490 const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1492 DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1493 DynamicList<word> allPatchTypes(allPatchNames.size());
1496 labelList from1ToAllPatches(patches1.size());
1497 labelList fromAllTo1Patches(allPatchNames.size(), -1);
1511 pointField allPoints;
1513 // Map from mesh0/1 points to allPoints.
1514 labelList from0ToAllPoints(mesh0.nPoints(), -1);
1515 labelList from1ToAllPoints(mesh1.nPoints(), -1);
1520 labelList allNeighbour;
1521 label nInternalFaces;
1523 labelList nFaces(allPatchNames.size(), 0);
1527 labelList from0ToAllFaces(mesh0.nFaces(), -1);
1528 labelList from1ToAllFaces(mesh1.nFaces(), -1);
1530 labelList from1ToAllCells(mesh1.nCells(), -1);
1538 allPatchNames.size(),
1562 DynamicList<word> pointZoneNames;
1563 List<DynamicList<label> > pzPoints;
1565 DynamicList<word> faceZoneNames;
1566 List<DynamicList<label> > fzFaces;
1567 List<DynamicList<bool> > fzFlips;
1569 DynamicList<word> cellZoneNames;
1570 List<DynamicList<label> > czCells;
1600 // Store mesh0 patch info before modifying patches0.
1601 labelList mesh0PatchSizes(getPatchSizes(patches0));
1602 labelList mesh0PatchStarts(getPatchStarts(patches0));
1604 // Map from 0 to all patches (since gets compacted)
1605 labelList from0ToAllPatches(patches0.size(), -1);
1607 // Inplace extend mesh0 patches (note that patches0.size() now also
1609 polyBoundaryMesh& allPatches =
1610 const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
1611 allPatches.setSize(allPatchNames.size());
1613 label startFaceI = nInternalFaces;
1615 // Copy patches0 with new sizes. First patches always come from
1616 // mesh0 and will always be present.
1617 label allPatchI = 0;
1619 forAll(from0ToAllPatches, patch0)
1621 // Originates from mesh0. Clone with new size & filter out empty
1624 if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
1626 //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
1628 from0ToAllPatches[patch0] = -1;
1629 // Check if patch was also in mesh1 and update its addressing if so.
1630 if (fromAllTo1Patches[patch0] != -1)
1632 from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1641 allPatches[patch0].clone
1650 // Record new index in allPatches
1651 from0ToAllPatches[patch0] = allPatchI;
1653 // Check if patch was also in mesh1 and update its addressing if so.
1654 if (fromAllTo1Patches[patch0] != -1)
1656 from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchI;
1659 startFaceI += nFaces[patch0];
1665 // Copy unique patches of mesh1.
1666 forAll(from1ToAllPatches, patch1)
1668 label uncompactAllPatchI = from1ToAllPatches[patch1];
1670 if (uncompactAllPatchI >= from0ToAllPatches.size())
1672 // Patch has not been merged with any mesh0 patch.
1676 nFaces[uncompactAllPatchI] == 0
1677 && isA<processorPolyPatch>(patches1[patch1])
1680 //Pout<< "Removing zero sized mesh1 patch "
1681 // << allPatchNames[uncompactAllPatchI] << endl;
1682 from1ToAllPatches[patch1] = -1;
1690 patches1[patch1].clone
1694 nFaces[uncompactAllPatchI],
1699 // Record new index in allPatches
1700 from1ToAllPatches[patch1] = allPatchI;
1702 startFaceI += nFaces[uncompactAllPatchI];
1709 allPatches.setSize(allPatchI);
1712 // Construct map information before changing mesh0 primitives
1713 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1715 autoPtr<mapAddedPolyMesh> mapPtr
1717 new mapAddedPolyMesh
1729 identity(mesh0.nCells()),
1745 // Now we have extracted all information from all meshes.
1746 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1748 labelList patchSizes(getPatchSizes(allPatches));
1749 labelList patchStarts(getPatchStarts(allPatches));
1751 mesh0.resetMotion(); // delete any oldPoints.
1752 mesh0.resetPrimitives
1754 xferMove(allPoints),
1757 xferMove(allNeighbour),
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
1933 // sharedPointLabels
1941 //// Find out which sets of points get merged and create a map from
1942 //// mesh point to unique point.
1944 //Map<label> pointToMaster(10*sharedToMerged.size());
1948 // labelListList mergeSets
1952 // sharedToMerged.size(),
1957 // label nMergeSets = 0;
1959 // forAll(mergeSets, setI)
1961 // const labelList& mergeSet = mergeSets[setI];
1963 // if (mergeSet.size() > 1)
1965 // // Take as master the shared point with the lowest mesh
1966 // // point label. (rather arbitrarily - could use max or
1967 // // any other one of the points)
1971 // label masterI = labelMax;
1973 // forAll(mergeSet, i)
1975 // label sharedI = mergeSet[i];
1977 // masterI = min(masterI, sharedPointLabels[sharedI]);
1980 // forAll(mergeSet, i)
1982 // label sharedI = mergeSet[i];
1984 // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
1991 // // Pout<< "polyMeshAdder : merging:"
1992 // // << pointToMaster.size() << " into " << nMergeSets
1993 // // << " sets." << endl;
1997 return pointToMaster;
2001 void Foam::polyMeshAdder::mergePoints
2003 const polyMesh& mesh,
2004 const Map<label>& pointToMaster,
2005 polyTopoChange& meshMod
2008 // Remove all non-master points.
2009 forAll(mesh.points(), pointI)
2011 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2013 if (iter != pointToMaster.end())
2015 if (iter() != pointI)
2017 meshMod.removePoint(pointI, iter());
2022 // Modify faces for points. Note: could use pointFaces here but want to
2023 // avoid addressing calculation.
2024 const faceList& faces = mesh.faces();
2026 forAll(faces, faceI)
2028 const face& f = faces[faceI];
2030 bool hasMerged = false;
2034 label pointI = f[fp];
2036 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2038 if (iter != pointToMaster.end())
2040 if (iter() != pointI)
2054 label pointI = f[fp];
2056 Map<label>::const_iterator iter = pointToMaster.find(pointI);
2058 if (iter != pointToMaster.end())
2064 label patchID = mesh.boundaryMesh().whichPatch(faceI);
2065 label nei = (patchID == -1 ? mesh.faceNeighbour()[faceI] : -1);
2066 label zoneID = mesh.faceZones().whichZone(faceI);
2067 bool zoneFlip = false;
2071 const faceZone& fZone = mesh.faceZones()[zoneID];
2072 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
2079 newF, // modified face
2080 faceI, // label of face
2081 mesh.faceOwner()[faceI], // owner
2084 patchID, // patch for face
2085 false, // remove from zone
2086 zoneID, // zone for face
2087 zoneFlip // face flip in zone
2095 // ************************************************************************* //