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 "meshRefinement.H"
29 #include "syncTools.H"
31 #include "refinementSurfaces.H"
34 #include "indirectPrimitivePatch.H"
35 #include "polyTopoChange.H"
36 #include "meshTools.H"
37 #include "polyModifyFace.H"
38 #include "polyModifyCell.H"
39 #include "polyAddFace.H"
40 #include "polyRemoveFace.H"
41 #include "polyAddPoint.H"
42 #include "localPointRegion.H"
43 #include "duplicatePoints.H"
45 #include "regionSplit.H"
46 #include "removeCells.H"
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
50 // Repatches external face or creates baffle for internal face
51 // with user specified patches (might be different for both sides).
52 // Returns label of added face.
53 Foam::label Foam::meshRefinement::createBaffle
58 polyTopoChange& meshMod
61 const face& f = mesh_.faces()[faceI];
62 label zoneID = mesh_.faceZones().whichZone(faceI);
63 bool zoneFlip = false;
67 const faceZone& fZone = mesh_.faceZones()[zoneID];
68 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
76 faceI, // label of face
77 mesh_.faceOwner()[faceI], // owner
80 ownPatch, // patch for face
81 false, // remove from zone
82 zoneID, // zone for face
83 zoneFlip // face flip in zone
90 if (mesh_.isInternalFace(faceI))
96 "meshRefinement::createBaffle"
97 "(const label, const label, const label, polyTopoChange&)"
98 ) << "No neighbour patch for internal face " << faceI
99 << " fc:" << mesh_.faceCentres()[faceI]
100 << " ownPatch:" << ownPatch << abort(FatalError);
103 bool reverseFlip = false;
106 reverseFlip = !zoneFlip;
109 dupFaceI = meshMod.setAction
113 f.reverseFace(), // modified face
114 mesh_.faceNeighbour()[faceI],// owner
118 faceI, // masterFaceID,
120 neiPatch, // patch for face
121 zoneID, // zone for face
122 reverseFlip // face flip in zone
130 // Get an estimate for the patch the internal face should get. Bit heuristic.
131 Foam::label Foam::meshRefinement::getBafflePatch
133 const labelList& facePatch,
137 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
139 // Loop over face points
140 // for each point check all faces patch IDs
141 // as soon as an ID >= 0 is found, break and assign that ID
142 // to the current face.
143 // Check first for real patch (so proper surface intersection and then
144 // in facePatch array for patches to block off faces
146 forAll(mesh_.faces()[faceI], fp)
148 label pointI = mesh_.faces()[faceI][fp];
150 forAll(mesh_.pointFaces()[pointI], pf)
152 label pFaceI = mesh_.pointFaces()[pointI][pf];
154 label patchI = patches.whichPatch(pFaceI);
156 if (patchI != -1 && !patches[patchI].coupled())
160 else if (facePatch[pFaceI] != -1)
162 return facePatch[pFaceI];
167 // Loop over owner and neighbour cells, looking for the first face with a
168 // valid patch number
169 const cell& ownFaces = mesh_.cells()[mesh_.faceOwner()[faceI]];
173 label cFaceI = ownFaces[i];
175 label patchI = patches.whichPatch(cFaceI);
177 if (patchI != -1 && !patches[patchI].coupled())
181 else if (facePatch[cFaceI] != -1)
183 return facePatch[cFaceI];
187 if (mesh_.isInternalFace(faceI))
189 const cell& neiFaces = mesh_.cells()[mesh_.faceNeighbour()[faceI]];
193 label cFaceI = neiFaces[i];
195 label patchI = patches.whichPatch(cFaceI);
197 if (patchI != -1 && !patches[patchI].coupled())
201 else if (facePatch[cFaceI] != -1)
203 return facePatch[cFaceI];
210 "meshRefinement::getBafflePatch(const labelList&, const label)"
211 ) << "Could not find boundary face neighbouring internal face "
212 << faceI << " with face centre " << mesh_.faceCentres()[faceI]
214 << "Using arbitrary patch " << 0 << " instead." << endl;
220 // Determine patches for baffles.
221 void Foam::meshRefinement::getBafflePatches
223 const labelList& globalToPatch,
224 const labelList& neiLevel,
225 const pointField& neiCc,
231 autoPtr<OFstream> str;
233 if (debug&OBJINTERSECTIONS)
239 mesh_.time().path()/timeName()/"intersections.obj"
243 Pout<< "getBafflePatches : Writing surface intersections to file "
244 << str().name() << nl << endl;
247 const pointField& cellCentres = mesh_.cellCentres();
249 // Build list of surfaces that are not to be baffled.
250 const wordList& cellZoneNames = surfaces_.cellZoneNames();
252 labelList surfacesToBaffle(cellZoneNames.size());
254 forAll(cellZoneNames, surfI)
256 if (cellZoneNames[surfI].size())
260 Pout<< "getBafflePatches : Not baffling surface "
261 << surfaces_.names()[surfI] << endl;
266 surfacesToBaffle[baffleI++] = surfI;
269 surfacesToBaffle.setSize(baffleI);
271 ownPatch.setSize(mesh_.nFaces());
273 neiPatch.setSize(mesh_.nFaces());
277 // Collect candidate faces
278 // ~~~~~~~~~~~~~~~~~~~~~~~
280 labelList testFaces(intersectedFaces());
285 pointField start(testFaces.size());
286 pointField end(testFaces.size());
290 label faceI = testFaces[i];
292 label own = mesh_.faceOwner()[faceI];
294 if (mesh_.isInternalFace(faceI))
296 start[i] = cellCentres[own];
297 end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
301 start[i] = cellCentres[own];
302 end[i] = neiCc[faceI-mesh_.nInternalFaces()];
307 // Do test for intersections
308 // ~~~~~~~~~~~~~~~~~~~~~~~~~
310 List<pointIndexHit> hit1;
313 List<pointIndexHit> hit2;
315 surfaces_.findNearestIntersection
332 label faceI = testFaces[i];
334 if (hit1[i].hit() && hit2[i].hit())
338 meshTools::writeOBJ(str(), start[i]);
340 meshTools::writeOBJ(str(), hit1[i].rawPoint());
342 meshTools::writeOBJ(str(), hit2[i].rawPoint());
344 meshTools::writeOBJ(str(), end[i]);
346 str()<< "l " << vertI-3 << ' ' << vertI-2 << nl;
347 str()<< "l " << vertI-2 << ' ' << vertI-1 << nl;
348 str()<< "l " << vertI-1 << ' ' << vertI << nl;
351 // Pick up the patches
352 ownPatch[faceI] = globalToPatch
354 surfaces_.globalRegion(surface1[i], region1[i])
356 neiPatch[faceI] = globalToPatch
358 surfaces_.globalRegion(surface2[i], region2[i])
361 if (ownPatch[faceI] == -1 || neiPatch[faceI] == -1)
363 FatalErrorIn("getBafflePatches(..)")
364 << "problem." << abort(FatalError);
369 // No need to parallel sync since intersection data (surfaceIndex_ etc.)
370 // already guaranteed to be synced...
372 // - owncc and neicc are reversed on different procs so might pick
373 // up different regions reversed? No problem. Neighbour on one processor
374 // might not be owner on the other processor but the neighbour is
375 // not used when creating baffles from proc faces.
376 // - tolerances issues occasionally crop up.
377 syncTools::syncFaceList(mesh_, ownPatch, maxEqOp<label>(), false);
378 syncTools::syncFaceList(mesh_, neiPatch, maxEqOp<label>(), false);
382 // Create baffle for every face where ownPatch != -1
383 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::createBaffles
385 const labelList& ownPatch,
386 const labelList& neiPatch
391 ownPatch.size() != mesh_.nFaces()
392 || neiPatch.size() != mesh_.nFaces()
397 "meshRefinement::createBaffles"
398 "(const labelList&, const labelList&)"
399 ) << "Illegal size :"
400 << " ownPatch:" << ownPatch.size()
401 << " neiPatch:" << neiPatch.size()
402 << ". Should be number of faces:" << mesh_.nFaces()
403 << abort(FatalError);
408 labelList syncedOwnPatch(ownPatch);
409 syncTools::syncFaceList(mesh_, syncedOwnPatch, maxEqOp<label>(), false);
410 labelList syncedNeiPatch(neiPatch);
411 syncTools::syncFaceList(mesh_, syncedNeiPatch, maxEqOp<label>(), false);
413 forAll(syncedOwnPatch, faceI)
417 (ownPatch[faceI] == -1 && syncedOwnPatch[faceI] != -1)
418 || (neiPatch[faceI] == -1 && syncedNeiPatch[faceI] != -1)
423 "meshRefinement::createBaffles"
424 "(const labelList&, const labelList&)"
425 ) << "Non synchronised at face:" << faceI
426 << " on patch:" << mesh_.boundaryMesh().whichPatch(faceI)
427 << " fc:" << mesh_.faceCentres()[faceI] << endl
428 << "ownPatch:" << ownPatch[faceI]
429 << " syncedOwnPatch:" << syncedOwnPatch[faceI]
430 << " neiPatch:" << neiPatch[faceI]
431 << " syncedNeiPatch:" << syncedNeiPatch[faceI]
432 << abort(FatalError);
437 // Topochange container
438 polyTopoChange meshMod(mesh_);
442 forAll(ownPatch, faceI)
444 if (ownPatch[faceI] != -1)
446 // Create baffle or repatch face. Return label of inserted baffle
451 ownPatch[faceI], // owner side patch
452 neiPatch[faceI], // neighbour side patch
459 // Change the mesh (no inflation, parallel sync)
460 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
463 mesh_.updateMesh(map);
465 // Move mesh if in inflation mode
466 if (map().hasMotionPoints())
468 mesh_.movePoints(map().preMotionPoints());
472 // Delete mesh volumes.
478 mesh_.setInstance(oldInstance());
481 //- Redo the intersections on the newly create baffle faces. Note that
482 // this changes also the cell centre positions.
483 faceSet baffledFacesSet(mesh_, "baffledFacesSet", 2*nBaffles);
485 const labelList& reverseFaceMap = map().reverseFaceMap();
486 const labelList& faceMap = map().faceMap();
488 // Pick up owner side of baffle
489 forAll(ownPatch, oldFaceI)
491 label faceI = reverseFaceMap[oldFaceI];
493 if (ownPatch[oldFaceI] != -1 && faceI >= 0)
495 const cell& ownFaces = mesh_.cells()[mesh_.faceOwner()[faceI]];
499 baffledFacesSet.insert(ownFaces[i]);
503 // Pick up neighbour side of baffle (added faces)
504 forAll(faceMap, faceI)
506 label oldFaceI = faceMap[faceI];
508 if (oldFaceI >= 0 && reverseFaceMap[oldFaceI] != faceI)
510 const cell& ownFaces = mesh_.cells()[mesh_.faceOwner()[faceI]];
514 baffledFacesSet.insert(ownFaces[i]);
518 baffledFacesSet.sync(mesh_);
520 updateMesh(map, baffledFacesSet.toc());
526 // Return a list of coupled face pairs, i.e. faces that use the same vertices.
527 // (this information is recalculated instead of maintained since would be too
528 // hard across splitMeshRegions).
529 Foam::List<Foam::labelPair> Foam::meshRefinement::getDuplicateFaces
531 const labelList& testFaces
534 labelList duplicateFace
536 localPointRegion::findDuplicateFaces
543 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
545 // Convert into list of coupled face pairs (mesh face labels).
546 List<labelPair> duplicateFaces(testFaces.size());
549 forAll(duplicateFace, i)
551 label otherFaceI = duplicateFace[i];
553 if (otherFaceI != -1 && i < otherFaceI)
555 label meshFace0 = testFaces[i];
556 label patch0 = patches.whichPatch(meshFace0);
557 label meshFace1 = testFaces[otherFaceI];
558 label patch1 = patches.whichPatch(meshFace1);
562 (patch0 != -1 && isA<processorPolyPatch>(patches[patch0]))
563 || (patch1 != -1 && isA<processorPolyPatch>(patches[patch1]))
568 "meshRefinement::getDuplicateFaces"
569 "(const bool, const labelList&)"
570 ) << "One of two duplicate faces is on"
571 << " processorPolyPatch."
572 << "This is not allowed." << nl
573 << "Face:" << meshFace0
574 << " is on patch:" << patches[patch0].name()
576 << "Face:" << meshFace1
577 << " is on patch:" << patches[patch1].name()
578 << abort(FatalError);
581 duplicateFaces[dupI++] = labelPair(meshFace0, meshFace1);
584 duplicateFaces.setSize(dupI);
586 Info<< "getDuplicateFaces : found " << returnReduce(dupI, sumOp<label>())
587 << " pairs of duplicate faces." << nl << endl;
592 faceSet duplicateFaceSet(mesh_, "duplicateFaces", 2*dupI);
594 forAll(duplicateFaces, i)
596 duplicateFaceSet.insert(duplicateFaces[i][0]);
597 duplicateFaceSet.insert(duplicateFaces[i][1]);
599 Pout<< "Writing duplicate faces (baffles) to faceSet "
600 << duplicateFaceSet.name() << nl << endl;
601 duplicateFaceSet.write();
604 return duplicateFaces;
608 // Extract those baffles (duplicate) faces that are on the edge of a baffle
609 // region. These are candidates for merging.
610 // Done by counting the number of baffles faces per mesh edge. If edge
611 // has 2 boundary faces and both are baffle faces it is the edge of a baffle
613 Foam::List<Foam::labelPair> Foam::meshRefinement::filterDuplicateFaces
615 const List<labelPair>& couples
618 // Construct addressing engine for all duplicate faces (only one
621 // Duplicate faces in mesh labels (first face of each pair only)
622 // (reused later on to mark off filtered couples. see below)
623 labelList duplicateFaces(couples.size());
626 // All duplicate faces on edge of the patch are to be merged.
627 // So we count for all edges of duplicate faces how many duplicate
629 labelList nBafflesPerEdge(mesh_.nEdges(), 0);
633 // Count number of boundary faces per edge
634 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
636 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
638 forAll(patches, patchI)
640 const polyPatch& pp = patches[patchI];
642 // Count number of boundary faces. Discard coupled boundary faces.
645 label faceI = pp.start();
649 const labelList& fEdges = mesh_.faceEdges(faceI);
651 forAll(fEdges, fEdgeI)
653 nBafflesPerEdge[fEdges[fEdgeI]]++;
661 DynamicList<label> fe0;
662 DynamicList<label> fe1;
665 // Count number of duplicate boundary faces per edge
666 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
670 const labelList& fEdges0 = mesh_.faceEdges(couples[i].first(), fe0);
672 forAll(fEdges0, fEdgeI)
674 nBafflesPerEdge[fEdges0[fEdgeI]] += 1000000;
677 const labelList& fEdges1 = mesh_.faceEdges(couples[i].second(), fe1);
679 forAll(fEdges1, fEdgeI)
681 nBafflesPerEdge[fEdges1[fEdgeI]] += 1000000;
685 // Add nBaffles on shared edges
686 syncTools::syncEdgeList
690 plusEqOp<label>(), // in-place add
692 false // no separation
696 // Baffles which are not next to other boundaries and baffles will have
697 // value 2*1000000+2*1
699 List<labelPair> filteredCouples(couples.size());
704 const labelPair& couple = couples[i];
708 patches.whichPatch(couple.first())
709 == patches.whichPatch(couple.second())
712 const labelList& fEdges = mesh_.faceEdges(couples[i].first());
714 forAll(fEdges, fEdgeI)
716 label edgeI = fEdges[fEdgeI];
718 if (nBafflesPerEdge[edgeI] == 2*1000000+2*1)
720 filteredCouples[filterI++] = couples[i];
726 filteredCouples.setSize(filterI);
728 //Info<< "filterDuplicateFaces : from "
729 // << returnReduce(couples.size(), sumOp<label>())
731 // << returnReduce(filteredCouples.size(), sumOp<label>())
732 // << " baffles." << nl << endl;
734 return filteredCouples;
738 // Merge baffles. Gets pairs of faces.
739 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::mergeBaffles
741 const List<labelPair>& couples
744 // Mesh change engine
745 polyTopoChange meshMod(mesh_);
747 const faceList& faces = mesh_.faces();
748 const labelList& faceOwner = mesh_.faceOwner();
749 const faceZoneMesh& faceZones = mesh_.faceZones();
753 label face0 = couples[i].first();
754 label face1 = couples[i].second();
756 // face1 < 0 signals a coupled face that has been converted to baffle.
758 label own0 = faceOwner[face0];
759 label own1 = faceOwner[face1];
761 if (face1 < 0 || own0 < own1)
763 // Use face0 as the new internal face.
764 label zoneID = faceZones.whichZone(face0);
765 bool zoneFlip = false;
769 const faceZone& fZone = faceZones[zoneID];
770 zoneFlip = fZone.flipMap()[fZone.whichFace(face0)];
773 label nei = (face1 < 0 ? -1 : own1);
775 meshMod.setAction(polyRemoveFace(face1));
780 faces[face0], // modified face
781 face0, // label of face being modified
785 -1, // patch for face
786 false, // remove from zone
787 zoneID, // zone for face
788 zoneFlip // face flip in zone
794 // Use face1 as the new internal face.
795 label zoneID = faceZones.whichZone(face1);
796 bool zoneFlip = false;
800 const faceZone& fZone = faceZones[zoneID];
801 zoneFlip = fZone.flipMap()[fZone.whichFace(face1)];
804 meshMod.setAction(polyRemoveFace(face0));
809 faces[face1], // modified face
810 face1, // label of face being modified
814 -1, // patch for face
815 false, // remove from zone
816 zoneID, // zone for face
817 zoneFlip // face flip in zone
823 // Change the mesh (no inflation)
824 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
827 mesh_.updateMesh(map);
829 // Move mesh (since morphing does not do this)
830 if (map().hasMotionPoints())
832 mesh_.movePoints(map().preMotionPoints());
836 // Delete mesh volumes.
842 mesh_.setInstance(oldInstance());
845 // Update intersections. Recalculate intersections on merged faces since
846 // this seems to give problems? Note: should not be nessecary since
847 // baffles preserve intersections from when they were created.
848 labelList newExposedFaces(2*couples.size());
853 label newFace0 = map().reverseFaceMap()[couples[i].first()];
856 newExposedFaces[newI++] = newFace0;
859 label newFace1 = map().reverseFaceMap()[couples[i].second()];
862 newExposedFaces[newI++] = newFace1;
865 newExposedFaces.setSize(newI);
866 updateMesh(map, newExposedFaces);
872 // Finds region per cell for cells inside closed named surfaces
873 void Foam::meshRefinement::findCellZoneGeometric
875 const labelList& closedNamedSurfaces, // indices of closed surfaces
876 labelList& namedSurfaceIndex, // per face index of named surface
877 const labelList& surfaceToCellZone, // cell zone index per surface
879 labelList& cellToZone
882 const pointField& cellCentres = mesh_.cellCentres();
883 const labelList& faceOwner = mesh_.faceOwner();
884 const labelList& faceNeighbour = mesh_.faceNeighbour();
886 // Check if cell centre is inside
887 labelList insideSurfaces;
895 forAll(insideSurfaces, cellI)
897 if (cellToZone[cellI] == -2)
899 label surfI = insideSurfaces[cellI];
903 cellToZone[cellI] = surfaceToCellZone[surfI];
909 // Some cells with cell centres close to surface might have
910 // had been put into wrong surface. Recheck with perturbed cell centre.
915 // Count points to test.
916 label nCandidates = 0;
917 forAll(namedSurfaceIndex, faceI)
919 label surfI = namedSurfaceIndex[faceI];
923 if (mesh_.isInternalFace(faceI))
935 pointField candidatePoints(nCandidates);
937 forAll(namedSurfaceIndex, faceI)
939 label surfI = namedSurfaceIndex[faceI];
943 label own = faceOwner[faceI];
944 const point& ownCc = cellCentres[own];
946 if (mesh_.isInternalFace(faceI))
948 label nei = faceNeighbour[faceI];
949 const point& neiCc = cellCentres[nei];
951 const vector d = 1E-4*(neiCc - ownCc);
952 candidatePoints[nCandidates++] = ownCc-d;
953 candidatePoints[nCandidates++] = neiCc+d;
957 const point& neiFc = mesh_.faceCentres()[faceI];
959 const vector d = 1E-4*(neiFc - ownCc);
960 candidatePoints[nCandidates++] = ownCc-d;
966 // 2. Test points for inside
976 // 3. Update zone information
979 forAll(namedSurfaceIndex, faceI)
981 label surfI = namedSurfaceIndex[faceI];
985 label own = faceOwner[faceI];
987 if (mesh_.isInternalFace(faceI))
989 label ownSurfI = insideSurfaces[nCandidates++];
992 cellToZone[own] = surfaceToCellZone[ownSurfI];
995 label neiSurfI = insideSurfaces[nCandidates++];
998 label nei = faceNeighbour[faceI];
1000 cellToZone[nei] = surfaceToCellZone[neiSurfI];
1005 label ownSurfI = insideSurfaces[nCandidates++];
1008 cellToZone[own] = surfaceToCellZone[ownSurfI];
1015 // Adapt the namedSurfaceIndex
1016 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1017 // for if any cells were not completely covered.
1019 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
1021 label ownZone = cellToZone[mesh_.faceOwner()[faceI]];
1022 label neiZone = cellToZone[mesh_.faceNeighbour()[faceI]];
1024 if (namedSurfaceIndex[faceI] == -1 && (ownZone != neiZone))
1026 // Give face the zone of max cell zone
1027 namedSurfaceIndex[faceI] = findIndex
1030 max(ownZone, neiZone)
1035 labelList neiCellZone(mesh_.nFaces()-mesh_.nInternalFaces());
1036 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1038 forAll(patches, patchI)
1040 const polyPatch& pp = patches[patchI];
1046 label faceI = pp.start()+i;
1047 label ownZone = cellToZone[mesh_.faceOwner()[faceI]];
1048 neiCellZone[faceI-mesh_.nInternalFaces()] = ownZone;
1052 syncTools::swapBoundaryFaceList(mesh_, neiCellZone, false);
1054 forAll(patches, patchI)
1056 const polyPatch& pp = patches[patchI];
1062 label faceI = pp.start()+i;
1063 label ownZone = cellToZone[mesh_.faceOwner()[faceI]];
1064 label neiZone = neiCellZone[faceI-mesh_.nInternalFaces()];
1066 if (namedSurfaceIndex[faceI] == -1 && (ownZone != neiZone))
1068 // Give face the max cell zone
1069 namedSurfaceIndex[faceI] = findIndex
1072 max(ownZone, neiZone)
1080 syncTools::syncFaceList
1090 bool Foam::meshRefinement::calcRegionToZone
1092 const label surfZoneI,
1093 const label ownRegion,
1094 const label neiRegion,
1096 labelList& regionToCellZone
1099 bool changed = false;
1101 // Check whether inbetween different regions
1102 if (ownRegion != neiRegion)
1104 // Jump. Change one of the sides to my type.
1106 // 1. Interface between my type and unset region.
1107 // Set region to keepRegion
1109 if (regionToCellZone[ownRegion] == -2)
1111 if (regionToCellZone[neiRegion] == surfZoneI)
1113 // Face between unset and my region. Put unset
1114 // region into keepRegion
1115 regionToCellZone[ownRegion] = -1;
1118 else if (regionToCellZone[neiRegion] != -2)
1120 // Face between unset and other region.
1121 // Put unset region into my region
1122 regionToCellZone[ownRegion] = surfZoneI;
1126 else if (regionToCellZone[neiRegion] == -2)
1128 if (regionToCellZone[ownRegion] == surfZoneI)
1130 // Face between unset and my region. Put unset
1131 // region into keepRegion
1132 regionToCellZone[neiRegion] = -1;
1135 else if (regionToCellZone[ownRegion] != -2)
1137 // Face between unset and other region.
1138 // Put unset region into my region
1139 regionToCellZone[neiRegion] = surfZoneI;
1148 // Finds region per cell. Assumes:
1149 // - region containing keepPoint does not go into a cellZone
1150 // - all other regions can be found by crossing faces marked in
1151 // namedSurfaceIndex.
1152 void Foam::meshRefinement::findCellZoneTopo
1154 const point& keepPoint,
1155 const labelList& namedSurfaceIndex,
1156 const labelList& surfaceToCellZone,
1157 labelList& cellToZone
1160 // Analyse regions. Reuse regionsplit
1161 boolList blockedFace(mesh_.nFaces());
1163 forAll(namedSurfaceIndex, faceI)
1165 if (namedSurfaceIndex[faceI] == -1)
1167 blockedFace[faceI] = false;
1171 blockedFace[faceI] = true;
1174 // No need to sync since namedSurfaceIndex already is synced
1176 // Set region per cell based on walking
1177 regionSplit cellRegion(mesh_, blockedFace);
1178 blockedFace.clear();
1180 // Per mesh region the zone the cell should be put in.
1181 // -2 : not analysed yet
1182 // -1 : keepPoint region. Not put into any cellzone.
1183 // >= 0 : index of cellZone
1184 labelList regionToCellZone(cellRegion.nRegions(), -2);
1186 // See which cells already are set in the cellToZone (from geometric
1187 // searching) and use these to take over their zones.
1188 // Note: could be improved to count number of cells per region.
1189 forAll(cellToZone, cellI)
1191 if (cellToZone[cellI] != -2)
1193 regionToCellZone[cellRegion[cellI]] = cellToZone[cellI];
1199 // Find the region containing the keepPoint
1200 label keepRegionI = -1;
1202 label cellI = mesh_.findCell(keepPoint);
1206 keepRegionI = cellRegion[cellI];
1208 reduce(keepRegionI, maxOp<label>());
1210 Info<< "Found point " << keepPoint << " in cell " << cellI
1211 << " in global region " << keepRegionI
1212 << " out of " << cellRegion.nRegions() << " regions." << endl;
1214 if (keepRegionI == -1)
1218 "meshRefinement::findCellZoneTopo"
1219 "(const point&, const labelList&, const labelList&, labelList&)"
1220 ) << "Point " << keepPoint
1221 << " is not inside the mesh." << nl
1222 << "Bounding box of the mesh:" << mesh_.globalData().bb()
1223 << exit(FatalError);
1226 // Mark default region with zone -1.
1227 if (regionToCellZone[keepRegionI] == -2)
1229 regionToCellZone[keepRegionI] = -1;
1233 // Find correspondence between cell zone and surface
1234 // by changing cell zone every time we cross a surface.
1237 // Synchronise regionToCellZone.
1239 // - region numbers are identical on all processors
1240 // - keepRegion is identical ,,
1241 // - cellZones are identical ,,
1242 // This done at top of loop to account for geometric matching
1243 // not being synchronised.
1244 Pstream::listCombineGather(regionToCellZone, maxEqOp<label>());
1245 Pstream::listCombineScatter(regionToCellZone);
1248 bool changed = false;
1252 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
1254 label surfI = namedSurfaceIndex[faceI];
1258 // Calculate region to zone from cellRegions on either side
1259 // of internal face.
1260 bool changedCell = calcRegionToZone
1262 surfaceToCellZone[surfI],
1263 cellRegion[mesh_.faceOwner()[faceI]],
1264 cellRegion[mesh_.faceNeighbour()[faceI]],
1268 changed = changed | changedCell;
1274 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1276 // Get coupled neighbour cellRegion
1277 labelList neiCellRegion(mesh_.nFaces()-mesh_.nInternalFaces());
1278 forAll(patches, patchI)
1280 const polyPatch& pp = patches[patchI];
1286 label faceI = pp.start()+i;
1287 neiCellRegion[faceI-mesh_.nInternalFaces()] =
1288 cellRegion[mesh_.faceOwner()[faceI]];
1292 syncTools::swapBoundaryFaceList(mesh_, neiCellRegion, false);
1294 // Calculate region to zone from cellRegions on either side of coupled
1296 forAll(patches, patchI)
1298 const polyPatch& pp = patches[patchI];
1304 label faceI = pp.start()+i;
1306 label surfI = namedSurfaceIndex[faceI];
1310 bool changedCell = calcRegionToZone
1312 surfaceToCellZone[surfI],
1313 cellRegion[mesh_.faceOwner()[faceI]],
1314 neiCellRegion[faceI-mesh_.nInternalFaces()],
1318 changed = changed | changedCell;
1324 if (!returnReduce(changed, orOp<bool>()))
1331 forAll(regionToCellZone, regionI)
1333 label zoneI = regionToCellZone[regionI];
1339 "meshRefinement::findCellZoneTopo"
1340 "(const point&, const labelList&, const labelList&, labelList&)"
1341 ) << "For region " << regionI << " haven't set cell zone."
1342 << exit(FatalError);
1348 forAll(regionToCellZone, regionI)
1350 Pout<< "Region " << regionI
1351 << " becomes cellZone:" << regionToCellZone[regionI]
1356 // Rework into cellToZone
1357 forAll(cellToZone, cellI)
1359 cellToZone[cellI] = regionToCellZone[cellRegion[cellI]];
1364 // Make namedSurfaceIndex consistent with cellToZone - clear out any blocked
1365 // faces inbetween same cell zone.
1366 void Foam::meshRefinement::makeConsistentFaceIndex
1368 const labelList& cellToZone,
1369 labelList& namedSurfaceIndex
1372 const labelList& faceOwner = mesh_.faceOwner();
1373 const labelList& faceNeighbour = mesh_.faceNeighbour();
1375 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
1377 label ownZone = cellToZone[faceOwner[faceI]];
1378 label neiZone = cellToZone[faceNeighbour[faceI]];
1380 if (ownZone == neiZone && namedSurfaceIndex[faceI] != -1)
1382 namedSurfaceIndex[faceI] = -1;
1384 else if (ownZone != neiZone && namedSurfaceIndex[faceI] == -1)
1386 FatalErrorIn("meshRefinement::zonify()")
1387 << "Different cell zones on either side of face " << faceI
1388 << " at " << mesh_.faceCentres()[faceI]
1389 << " but face not marked with a surface."
1390 << abort(FatalError);
1394 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
1396 // Get coupled neighbour cellZone
1397 labelList neiCellZone(mesh_.nFaces()-mesh_.nInternalFaces());
1398 forAll(patches, patchI)
1400 const polyPatch& pp = patches[patchI];
1406 label faceI = pp.start()+i;
1407 neiCellZone[faceI-mesh_.nInternalFaces()] =
1408 cellToZone[mesh_.faceOwner()[faceI]];
1412 syncTools::swapBoundaryFaceList(mesh_, neiCellZone, false);
1414 // Use coupled cellZone to do check
1415 forAll(patches, patchI)
1417 const polyPatch& pp = patches[patchI];
1423 label faceI = pp.start()+i;
1425 label ownZone = cellToZone[faceOwner[faceI]];
1426 label neiZone = neiCellZone[faceI-mesh_.nInternalFaces()];
1428 if (ownZone == neiZone && namedSurfaceIndex[faceI] != -1)
1430 namedSurfaceIndex[faceI] = -1;
1432 else if (ownZone != neiZone && namedSurfaceIndex[faceI] == -1)
1434 FatalErrorIn("meshRefinement::zonify()")
1435 << "Different cell zones on either side of face "
1436 << faceI << " at " << mesh_.faceCentres()[faceI]
1437 << " but face not marked with a surface."
1438 << abort(FatalError);
1446 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1448 // Split off unreachable areas of mesh.
1449 void Foam::meshRefinement::baffleAndSplitMesh
1451 const bool handleSnapProblems,
1452 const bool removeEdgeConnectedCells,
1453 const scalarField& perpendicularAngle,
1454 const bool mergeFreeStanding,
1455 const dictionary& motionDict,
1457 const labelList& globalToPatch,
1458 const point& keepPoint
1461 // Introduce baffles
1462 // ~~~~~~~~~~~~~~~~~
1464 // Split the mesh along internal faces wherever there is a pierce between
1465 // two cell centres.
1467 Info<< "Introducing baffles for "
1468 << returnReduce(countHits(), sumOp<label>())
1469 << " faces that are intersected by the surface." << nl << endl;
1471 // Swap neighbouring cell centres and cell level
1472 labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1473 pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
1474 calcNeighbourData(neiLevel, neiCc);
1476 labelList ownPatch, neiPatch;
1492 createBaffles(ownPatch, neiPatch);
1496 // Debug:test all is still synced across proc patches
1500 Info<< "Created baffles in = "
1501 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1503 printMeshInfo(debug, "After introducing baffles");
1507 Pout<< "Writing baffled mesh to time " << timeName()
1509 write(debug, runTime.path()/"baffles");
1510 Pout<< "Dumped debug data in = "
1511 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1515 // Introduce baffles to delete problem cells
1516 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1518 // Create some additional baffles where we want surface cells removed.
1520 if (handleSnapProblems)
1523 << "Introducing baffles to block off problem cells" << nl
1524 << "----------------------------------------------" << nl
1529 markFacesOnProblemCells
1532 removeEdgeConnectedCells,
1536 //markFacesOnProblemCellsGeometric(motionDict)
1538 Info<< "Analyzed problem cells in = "
1539 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1543 faceSet problemTopo(mesh_, "problemFacesTopo", 100);
1545 const labelList facePatchTopo
1547 markFacesOnProblemCells
1550 removeEdgeConnectedCells,
1555 forAll(facePatchTopo, faceI)
1557 if (facePatchTopo[faceI] != -1)
1559 problemTopo.insert(faceI);
1562 Pout<< "Dumping " << problemTopo.size()
1563 << " problem faces to " << problemTopo.objectPath() << endl;
1564 problemTopo.write();
1567 Info<< "Introducing baffles to delete problem cells." << nl << endl;
1574 // Create baffles with same owner and neighbour for now.
1575 createBaffles(facePatch, facePatch);
1579 // Debug:test all is still synced across proc patches
1582 Info<< "Created baffles in = "
1583 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1585 printMeshInfo(debug, "After introducing baffles");
1589 Pout<< "Writing extra baffled mesh to time "
1590 << timeName() << endl;
1591 write(debug, runTime.path()/"extraBaffles");
1592 Pout<< "Dumped debug data in = "
1593 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1598 // Select part of mesh
1599 // ~~~~~~~~~~~~~~~~~~~
1602 << "Remove unreachable sections of mesh" << nl
1603 << "-----------------------------------" << nl
1611 splitMeshRegions(keepPoint);
1615 // Debug:test all is still synced across proc patches
1618 Info<< "Split mesh in = "
1619 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1621 printMeshInfo(debug, "After subsetting");
1625 Pout<< "Writing subsetted mesh to time " << timeName()
1627 write(debug, runTime.path()/timeName());
1628 Pout<< "Dumped debug data in = "
1629 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1636 if (mergeFreeStanding)
1639 << "Merge free-standing baffles" << nl
1640 << "---------------------------" << nl
1648 // List of pairs of freestanding baffle faces.
1649 List<labelPair> couples
1651 filterDuplicateFaces // filter out freestanding baffles
1653 getDuplicateFaces // get all baffles
1655 identity(mesh_.nFaces()-mesh_.nInternalFaces())
1656 +mesh_.nInternalFaces()
1661 label nCouples = couples.size();
1662 reduce(nCouples, sumOp<label>());
1664 Info<< "Detected free-standing baffles : " << nCouples << endl;
1668 // Actually merge baffles. Note: not exactly parallellized. Should
1669 // convert baffle faces into processor faces if they resulted
1671 mergeBaffles(couples);
1675 // Debug:test all is still synced across proc patches
1679 Info<< "Merged free-standing baffles in = "
1680 << runTime.cpuTimeIncrement() << " s\n" << nl << endl;
1685 // Split off (with optional buffer layers) unreachable areas of mesh.
1686 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::splitMesh
1688 const label nBufferLayers,
1689 const labelList& globalToPatch,
1690 const point& keepPoint
1693 // Determine patches to put intersections into
1694 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1696 // Swap neighbouring cell centres and cell level
1697 labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1698 pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
1699 calcNeighbourData(neiLevel, neiCc);
1701 labelList ownPatch, neiPatch;
1712 // Analyse regions. Reuse regionsplit
1713 boolList blockedFace(mesh_.nFaces(), false);
1715 forAll(ownPatch, faceI)
1717 if (ownPatch[faceI] != -1 || neiPatch[faceI] != -1)
1719 blockedFace[faceI] = true;
1722 syncTools::syncFaceList(mesh_, blockedFace, orEqOp<bool>(), false);
1724 // Set region per cell based on walking
1725 regionSplit cellRegion(mesh_, blockedFace);
1726 blockedFace.clear();
1728 // Find the region containing the keepPoint
1729 label keepRegionI = -1;
1731 label cellI = mesh_.findCell(keepPoint);
1735 keepRegionI = cellRegion[cellI];
1737 reduce(keepRegionI, maxOp<label>());
1739 Info<< "Found point " << keepPoint << " in cell " << cellI
1740 << " in global region " << keepRegionI
1741 << " out of " << cellRegion.nRegions() << " regions." << endl;
1743 if (keepRegionI == -1)
1747 "meshRefinement::splitMesh"
1748 "(const label, const labelList&, const point&)"
1749 ) << "Point " << keepPoint
1750 << " is not inside the mesh." << nl
1751 << "Bounding box of the mesh:" << mesh_.globalData().bb()
1752 << exit(FatalError);
1756 // Walk out nBufferlayers from region split
1757 // (modifies cellRegion, ownPatch)
1758 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1759 // Takes over face patch onto points and then back to faces and cells
1760 // (so cell-face-point walk)
1762 const labelList& faceOwner = mesh_.faceOwner();
1763 const labelList& faceNeighbour = mesh_.faceNeighbour();
1765 // Patch for exposed faces for lack of anything sensible.
1766 label defaultPatch = 0;
1767 if (globalToPatch.size())
1769 defaultPatch = globalToPatch[0];
1772 for (label i = 0; i < nBufferLayers; i++)
1774 // 1. From cells (via faces) to points
1776 labelList pointBaffle(mesh_.nPoints(), -1);
1778 forAll(faceNeighbour, faceI)
1780 const face& f = mesh_.faces()[faceI];
1782 label ownRegion = cellRegion[faceOwner[faceI]];
1783 label neiRegion = cellRegion[faceNeighbour[faceI]];
1785 if (ownRegion == keepRegionI && neiRegion != keepRegionI)
1787 // Note max(..) since possibly regionSplit might have split
1788 // off extra unreachable parts of mesh. Note: or can this only
1789 // happen for boundary faces?
1792 pointBaffle[f[fp]] = max(defaultPatch, ownPatch[faceI]);
1795 else if (ownRegion != keepRegionI && neiRegion == keepRegionI)
1797 label newPatchI = neiPatch[faceI];
1798 if (newPatchI == -1)
1800 newPatchI = max(defaultPatch, ownPatch[faceI]);
1804 pointBaffle[f[fp]] = newPatchI;
1810 label faceI = mesh_.nInternalFaces();
1811 faceI < mesh_.nFaces();
1815 const face& f = mesh_.faces()[faceI];
1817 label ownRegion = cellRegion[faceOwner[faceI]];
1819 if (ownRegion == keepRegionI)
1823 pointBaffle[f[fp]] = max(defaultPatch, ownPatch[faceI]);
1829 syncTools::syncPointList
1835 false // no separation
1839 // 2. From points back to faces
1841 const labelListList& pointFaces = mesh_.pointFaces();
1843 forAll(pointFaces, pointI)
1845 if (pointBaffle[pointI] != -1)
1847 const labelList& pFaces = pointFaces[pointI];
1849 forAll(pFaces, pFaceI)
1851 label faceI = pFaces[pFaceI];
1853 if (ownPatch[faceI] == -1)
1855 ownPatch[faceI] = pointBaffle[pointI];
1860 syncTools::syncFaceList(mesh_, ownPatch, maxEqOp<label>(), false);
1863 // 3. From faces to cells (cellRegion) and back to faces (ownPatch)
1865 labelList newOwnPatch(ownPatch);
1867 forAll(ownPatch, faceI)
1869 if (ownPatch[faceI] != -1)
1871 label own = faceOwner[faceI];
1873 if (cellRegion[own] != keepRegionI)
1875 cellRegion[own] = keepRegionI;
1877 const cell& ownFaces = mesh_.cells()[own];
1880 if (ownPatch[ownFaces[j]] == -1)
1882 newOwnPatch[ownFaces[j]] = ownPatch[faceI];
1886 if (mesh_.isInternalFace(faceI))
1888 label nei = faceNeighbour[faceI];
1890 if (cellRegion[nei] != keepRegionI)
1892 cellRegion[nei] = keepRegionI;
1894 const cell& neiFaces = mesh_.cells()[nei];
1897 if (ownPatch[neiFaces[j]] == -1)
1899 newOwnPatch[neiFaces[j]] = ownPatch[faceI];
1907 ownPatch.transfer(newOwnPatch);
1909 syncTools::syncFaceList(mesh_, ownPatch, maxEqOp<label>(), false);
1917 // Get cells to remove
1918 DynamicList<label> cellsToRemove(mesh_.nCells());
1919 forAll(cellRegion, cellI)
1921 if (cellRegion[cellI] != keepRegionI)
1923 cellsToRemove.append(cellI);
1926 cellsToRemove.shrink();
1928 label nCellsToKeep = mesh_.nCells() - cellsToRemove.size();
1929 reduce(nCellsToKeep, sumOp<label>());
1931 Info<< "Keeping all cells in region " << keepRegionI
1932 << " containing point " << keepPoint << endl
1933 << "Selected for keeping : " << nCellsToKeep
1934 << " cells." << endl;
1938 removeCells cellRemover(mesh_);
1940 // Pick up patches for exposed faces
1941 labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
1942 labelList exposedPatches(exposedFaces.size());
1944 forAll(exposedFaces, i)
1946 label faceI = exposedFaces[i];
1948 if (ownPatch[faceI] != -1)
1950 exposedPatches[i] = ownPatch[faceI];
1954 WarningIn("meshRefinement::splitMesh(..)")
1955 << "For exposed face " << faceI
1956 << " fc:" << mesh_.faceCentres()[faceI]
1957 << " found no patch." << endl
1958 << " Taking patch " << defaultPatch
1959 << " instead." << endl;
1960 exposedPatches[i] = defaultPatch;
1964 return doRemoveCells
1974 // Find boundary points that connect to more than one cell region and
1976 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::dupNonManifoldPoints()
1978 // Topochange container
1979 polyTopoChange meshMod(mesh_);
1982 // Analyse which points need to be duplicated
1983 localPointRegion regionSide(mesh_);
1985 label nNonManifPoints = returnReduce
1987 regionSide.meshPointMap().size(),
1991 Info<< "dupNonManifoldPoints : Found : " << nNonManifPoints
1992 << " non-manifold points (out of "
1993 << mesh_.globalData().nTotalPoints()
1996 // Topo change engine
1997 duplicatePoints pointDuplicator(mesh_);
1999 // Insert changes into meshMod
2000 pointDuplicator.setRefinement(regionSide, meshMod);
2002 // Change the mesh (no inflation, parallel sync)
2003 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
2006 mesh_.updateMesh(map);
2008 // Move mesh if in inflation mode
2009 if (map().hasMotionPoints())
2011 mesh_.movePoints(map().preMotionPoints());
2015 // Delete mesh volumes.
2021 mesh_.setInstance(oldInstance());
2024 // Update intersections. Is mapping only (no faces created, positions stay
2025 // same) so no need to recalculate intersections.
2026 updateMesh(map, labelList(0));
2033 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::zonify
2035 const point& keepPoint
2038 const wordList& cellZoneNames = surfaces_.cellZoneNames();
2039 const wordList& faceZoneNames = surfaces_.faceZoneNames();
2041 labelList namedSurfaces(surfaces_.getNamedSurfaces());
2043 boolList isNamedSurface(cellZoneNames.size(), false);
2045 forAll(namedSurfaces, i)
2047 label surfI = namedSurfaces[i];
2049 isNamedSurface[surfI] = true;
2051 Info<< "Surface : " << surfaces_.names()[surfI] << nl
2052 << " faceZone : " << faceZoneNames[surfI] << nl
2053 << " cellZone : " << cellZoneNames[surfI] << endl;
2057 // Add zones to mesh
2059 labelList surfaceToFaceZone(faceZoneNames.size(), -1);
2061 faceZoneMesh& faceZones = mesh_.faceZones();
2063 forAll(namedSurfaces, i)
2065 label surfI = namedSurfaces[i];
2067 label zoneI = faceZones.findZoneID(faceZoneNames[surfI]);
2071 zoneI = faceZones.size();
2072 faceZones.setSize(zoneI+1);
2078 faceZoneNames[surfI], //name
2079 labelList(0), //addressing
2080 boolList(0), //flipmap
2082 faceZones //faceZoneMesh
2089 Pout<< "Faces on " << surfaces_.names()[surfI]
2090 << " will go into faceZone " << zoneI << endl;
2092 surfaceToFaceZone[surfI] = zoneI;
2095 // Check they are synced
2096 List<wordList> allFaceZones(Pstream::nProcs());
2097 allFaceZones[Pstream::myProcNo()] = faceZones.names();
2098 Pstream::gatherList(allFaceZones);
2099 Pstream::scatterList(allFaceZones);
2101 for (label procI = 1; procI < allFaceZones.size(); procI++)
2103 if (allFaceZones[procI] != allFaceZones[0])
2107 "meshRefinement::zonify"
2108 "(const label, const point&)"
2109 ) << "Zones not synchronised among processors." << nl
2110 << " Processor0 has faceZones:" << allFaceZones[0]
2111 << " , processor" << procI
2112 << " has faceZones:" << allFaceZones[procI]
2113 << exit(FatalError);
2118 labelList surfaceToCellZone(cellZoneNames.size(), -1);
2120 cellZoneMesh& cellZones = mesh_.cellZones();
2122 forAll(namedSurfaces, i)
2124 label surfI = namedSurfaces[i];
2126 label zoneI = cellZones.findZoneID(cellZoneNames[surfI]);
2130 zoneI = cellZones.size();
2131 cellZones.setSize(zoneI+1);
2137 cellZoneNames[surfI], //name
2138 labelList(0), //addressing
2140 cellZones //cellZoneMesh
2147 Pout<< "Cells inside " << surfaces_.names()[surfI]
2148 << " will go into cellZone " << zoneI << endl;
2150 surfaceToCellZone[surfI] = zoneI;
2153 // Check they are synced
2154 List<wordList> allCellZones(Pstream::nProcs());
2155 allCellZones[Pstream::myProcNo()] = cellZones.names();
2156 Pstream::gatherList(allCellZones);
2157 Pstream::scatterList(allCellZones);
2159 for (label procI = 1; procI < allCellZones.size(); procI++)
2161 if (allCellZones[procI] != allCellZones[0])
2165 "meshRefinement::zonify"
2166 "(const label, const point&)"
2167 ) << "Zones not synchronised among processors." << nl
2168 << " Processor0 has cellZones:" << allCellZones[0]
2169 << " , processor" << procI
2170 << " has cellZones:" << allCellZones[procI]
2171 << exit(FatalError);
2178 const pointField& cellCentres = mesh_.cellCentres();
2179 const labelList& faceOwner = mesh_.faceOwner();
2180 const labelList& faceNeighbour = mesh_.faceNeighbour();
2181 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
2184 // Mark faces intersecting zoned surfaces
2185 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2188 // Like surfaceIndex_ but only for named surfaces.
2189 labelList namedSurfaceIndex(mesh_.nFaces(), -1);
2192 // Statistics: number of faces per faceZone
2193 labelList nSurfFaces(faceZoneNames.size(), 0);
2195 // Swap neighbouring cell centres and cell level
2196 labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
2197 pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
2198 calcNeighbourData(neiLevel, neiCc);
2200 // Note: for all internal faces? internal + coupled?
2201 // Since zonify is run after baffling the surfaceIndex_ on baffles is
2202 // not synchronised across both baffle faces. Fortunately we don't
2203 // do zonify baffle faces anyway (they are normal boundary faces).
2205 // Collect candidate faces
2206 // ~~~~~~~~~~~~~~~~~~~~~~~
2208 labelList testFaces(intersectedFaces());
2213 pointField start(testFaces.size());
2214 pointField end(testFaces.size());
2216 forAll(testFaces, i)
2218 label faceI = testFaces[i];
2220 if (mesh_.isInternalFace(faceI))
2222 start[i] = cellCentres[faceOwner[faceI]];
2223 end[i] = cellCentres[faceNeighbour[faceI]];
2227 start[i] = cellCentres[faceOwner[faceI]];
2228 end[i] = neiCc[faceI-mesh_.nInternalFaces()];
2233 // Do test for intersections
2234 // ~~~~~~~~~~~~~~~~~~~~~~~~~
2235 // Note that we intersect all intersected faces again. Could reuse
2236 // the information already in surfaceIndex_.
2241 List<pointIndexHit> hit1;
2243 List<pointIndexHit> hit2;
2245 surfaces_.findNearestIntersection
2260 forAll(testFaces, i)
2262 label faceI = testFaces[i];
2264 if (surface1[i] != -1)
2266 // If both hit should probably choose nearest. For later.
2267 namedSurfaceIndex[faceI] = surface1[i];
2268 nSurfFaces[surface1[i]]++;
2270 else if (surface2[i] != -1)
2272 namedSurfaceIndex[faceI] = surface2[i];
2273 nSurfFaces[surface2[i]]++;
2278 // surfaceIndex migh have different surfaces on both sides if
2279 // there happen to be a (obviously thin) surface with different
2280 // regions between the cell centres. If one is on a named surface
2281 // and the other is not this might give problems so sync.
2282 syncTools::syncFaceList
2293 forAll(nSurfFaces, surfI)
2296 << surfaces_.names()[surfI]
2297 << " nZoneFaces:" << nSurfFaces[surfI] << nl;
2304 // Put the cells into the correct zone
2305 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2307 // Closed surfaces with cellZone specified.
2308 labelList closedNamedSurfaces(surfaces_.getClosedNamedSurfaces());
2312 // -1 : not in any zone
2314 labelList cellToZone(mesh_.nCells(), -2);
2317 // Set using geometric test
2318 // ~~~~~~~~~~~~~~~~~~~~~~~~
2320 if (closedNamedSurfaces.size())
2322 findCellZoneGeometric
2324 closedNamedSurfaces, // indices of closed surfaces
2325 namedSurfaceIndex, // per face index of named surface
2326 surfaceToCellZone, // cell zone index per surface
2331 // Set using walking
2332 // ~~~~~~~~~~~~~~~~~
2334 //if (returnReduce(nSet, sumOp<label>()) < mesh_.globalData().nTotalCells())
2347 //// Make sure namedSurfaceIndex is unset inbetween same cell cell zones.
2348 //makeConsistentFaceIndex(cellToZone, namedSurfaceIndex);
2351 // Topochange container
2352 polyTopoChange meshMod(mesh_);
2355 // Put the faces into the correct zone
2356 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2358 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
2360 label surfI = namedSurfaceIndex[faceI];
2364 // Orient face zone to have slave cells in max cell zone.
2365 label ownZone = cellToZone[faceOwner[faceI]];
2366 label neiZone = cellToZone[faceNeighbour[faceI]];
2369 if (ownZone == max(ownZone, neiZone))
2382 mesh_.faces()[faceI], // modified face
2383 faceI, // label of face
2384 faceOwner[faceI], // owner
2385 faceNeighbour[faceI], // neighbour
2387 -1, // patch for face
2388 false, // remove from zone
2389 surfaceToFaceZone[surfI], // zone for face
2390 flip // face flip in zone
2396 // Get coupled neighbour cellZone. Set to -1 on non-coupled patches.
2397 labelList neiCellZone(mesh_.nFaces()-mesh_.nInternalFaces(), -1);
2398 forAll(patches, patchI)
2400 const polyPatch& pp = patches[patchI];
2406 label faceI = pp.start()+i;
2407 neiCellZone[faceI-mesh_.nInternalFaces()] =
2408 cellToZone[mesh_.faceOwner()[faceI]];
2412 syncTools::swapBoundaryFaceList(mesh_, neiCellZone, false);
2414 // Set owner as no-flip
2415 forAll(patches, patchI)
2417 const polyPatch& pp = patches[patchI];
2419 label faceI = pp.start();
2423 label surfI = namedSurfaceIndex[faceI];
2427 label ownZone = cellToZone[faceOwner[faceI]];
2428 label neiZone = neiCellZone[faceI-mesh_.nInternalFaces()];
2431 if (ownZone == max(ownZone, neiZone))
2444 mesh_.faces()[faceI], // modified face
2445 faceI, // label of face
2446 faceOwner[faceI], // owner
2449 patchI, // patch for face
2450 false, // remove from zone
2451 surfaceToFaceZone[surfI], // zone for face
2452 flip // face flip in zone
2461 // Put the cells into the correct zone
2462 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2464 forAll(cellToZone, cellI)
2466 label zoneI = cellToZone[cellI];
2475 false, // removeFromZone
2482 // Change the mesh (no inflation, parallel sync)
2483 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
2486 mesh_.updateMesh(map);
2488 // Move mesh if in inflation mode
2489 if (map().hasMotionPoints())
2491 mesh_.movePoints(map().preMotionPoints());
2495 // Delete mesh volumes.
2501 mesh_.setInstance(oldInstance());
2504 // None of the faces has changed, only the zones. Still...
2505 updateMesh(map, labelList());
2511 // ************************************************************************* //