1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "regionSplit.H"
27 #include "cyclicPolyPatch.H"
28 #include "processorPolyPatch.H"
29 #include "globalIndex.H"
30 #include "syncTools.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 defineTypeNameAndDebug(regionSplit, 0);
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 // Handle (non-processor) coupled faces.
44 void Foam::regionSplit::transferCoupledFaceRegion
47 const label otherFaceI,
49 labelList& faceRegion,
50 dynamicLabelList& newChangedFaces
53 if (faceRegion[faceI] >= 0)
55 if (faceRegion[otherFaceI] == -1)
57 faceRegion[otherFaceI] = faceRegion[faceI];
58 newChangedFaces.append(otherFaceI);
60 else if (faceRegion[otherFaceI] == -2)
62 // otherFaceI blocked but faceI is not. Is illegal for coupled
63 // faces, not for explicit connections.
65 else if (faceRegion[otherFaceI] != faceRegion[faceI])
69 "regionSplit::transferCoupledFaceRegion"
70 "(const label, const label, labelList&, labelList&) const"
71 ) << "Problem : coupled face " << faceI
72 << " on patch " << mesh_.boundaryMesh().whichPatch(faceI)
73 << " has region " << faceRegion[faceI]
74 << " but coupled face " << otherFaceI
75 << " has region " << faceRegion[otherFaceI]
77 << "Is your blocked faces specification"
78 << " synchronized across coupled boundaries?"
82 else if (faceRegion[faceI] == -1)
84 if (faceRegion[otherFaceI] >= 0)
86 faceRegion[faceI] = faceRegion[otherFaceI];
87 newChangedFaces.append(faceI);
89 else if (faceRegion[otherFaceI] == -2)
91 // otherFaceI blocked but faceI is not. Is illegal for coupled
92 // faces, not for explicit connections.
98 void Foam::regionSplit::fillSeedMask
100 const List<labelPair>& explicitConnections,
101 labelList& cellRegion,
102 labelList& faceRegion,
103 const label seedCellID,
104 const label markValue
108 cellRegion[seedCellID] = markValue;
111 // Collect faces on seed cell
112 const cell& cFaces = mesh_.cells()[seedCellID];
116 labelList changedFaces(cFaces.size());
120 label faceI = cFaces[i];
122 if (faceRegion[faceI] == -1)
124 faceRegion[faceI] = markValue;
125 changedFaces[nFaces++] = faceI;
128 changedFaces.setSize(nFaces);
131 // Loop over changed faces. MeshWave in small.
133 while (changedFaces.size())
137 // Pout<< "regionSplit::fillSeedMask : changedFaces:"
138 // << changedFaces.size() << endl;
141 dynamicLabelList changedCells(changedFaces.size());
143 forAll(changedFaces, i)
145 label faceI = changedFaces[i];
147 label own = mesh_.faceOwner()[faceI];
149 if (cellRegion[own] == -1)
151 cellRegion[own] = markValue;
152 changedCells.append(own);
155 if (mesh_.isInternalFace(faceI))
157 label nei = mesh_.faceNeighbour()[faceI];
159 if (cellRegion[nei] == -1)
161 cellRegion[nei] = markValue;
162 changedCells.append(nei);
170 // Pout<< "regionSplit::fillSeedMask : changedCells:"
171 // << changedCells.size() << endl;
174 // Loop over changedCells and collect faces
175 dynamicLabelList newChangedFaces(changedCells.size());
177 forAll(changedCells, i)
179 label cellI = changedCells[i];
181 const cell& cFaces = mesh_.cells()[cellI];
183 forAll(cFaces, cFaceI)
185 label faceI = cFaces[cFaceI];
187 if (faceRegion[faceI] == -1)
189 faceRegion[faceI] = markValue;
190 newChangedFaces.append(faceI);
198 // Pout<< "regionSplit::fillSeedMask : changedFaces before sync:"
199 // << changedFaces.size() << endl;
203 // Check for changes to any locally coupled face.
204 // Global connections are done later.
206 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
208 forAll(patches, patchI)
210 const polyPatch& pp = patches[patchI];
212 if (isA<cyclicPolyPatch>(pp))
214 label faceI = pp.start();
216 label halfSz = pp.size()/2;
218 for (label i = 0; i < halfSz; i++)
220 label otherFaceI = refCast<const cyclicPolyPatch>(pp)
221 .transformGlobalFace(faceI);
223 transferCoupledFaceRegion
235 forAll(explicitConnections, i)
237 transferCoupledFaceRegion
239 explicitConnections[i][0],
240 explicitConnections[i][1],
248 // Pout<< "regionSplit::fillSeedMask : changedFaces after sync:"
249 // << newChangedFaces.size() << endl;
252 changedFaces.transfer(newChangedFaces);
257 Foam::label Foam::regionSplit::calcRegionSplit
259 const boolList& blockedFace,
260 const List<labelPair>& explicitConnections,
262 labelList& cellRegion
267 if (blockedFace.size())
269 // Check that blockedFace is synced.
270 boolList syncBlockedFace(blockedFace);
271 syncTools::swapFaceList(mesh_, syncBlockedFace, false);
273 forAll(syncBlockedFace, faceI)
275 if (syncBlockedFace[faceI] != blockedFace[faceI])
279 "regionSplit::calcRegionSplit(..)"
280 ) << "Face " << faceI << " not synchronised. My value:"
281 << blockedFace[faceI] << " coupled value:"
282 << syncBlockedFace[faceI]
283 << abort(FatalError);
292 labelList faceRegion(mesh_.nFaces(), -1);
294 if (blockedFace.size())
296 forAll(blockedFace, faceI)
298 if (blockedFace[faceI])
300 faceRegion[faceI] = -2;
306 // Assign local regions
307 // ~~~~~~~~~~~~~~~~~~~~
309 // Start with region 0
312 label unsetCellI = 0;
316 // Find first unset cell
318 for (; unsetCellI < mesh_.nCells(); unsetCellI++)
320 if (cellRegion[unsetCellI] == -1)
326 if (unsetCellI >= mesh_.nCells())
340 // Current unsetCell has now been handled. Go to next region.
349 forAll(cellRegion, cellI)
351 if (cellRegion[cellI] < 0)
353 FatalErrorIn("regionSplit::calcRegionSplit(..)")
354 << "cell:" << cellI << " region:" << cellRegion[cellI]
355 << abort(FatalError);
359 forAll(faceRegion, faceI)
361 if (faceRegion[faceI] == -1)
363 FatalErrorIn("regionSplit::calcRegionSplit(..)")
364 << "face:" << faceI << " region:" << faceRegion[faceI]
365 << abort(FatalError);
372 // Assign global regions
373 // ~~~~~~~~~~~~~~~~~~~~~
374 // Offset local regions to create unique global regions.
376 globalIndex globalRegions(nRegions);
379 // Merge global regions
380 // ~~~~~~~~~~~~~~~~~~~~
381 // Regions across non-blocked proc patches get merged.
382 // This will set merged global regions to be the min of both.
383 // (this will create gaps in the global region list so they will get
386 // Map from global to merged global
387 labelList mergedGlobal(identity(globalRegions.size()));
390 // See if any regions get merged. Only nessecary for parallel
391 while (Pstream::parRun())
395 Pout<< nl << "-- Starting Iteration --" << endl;
398 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
400 // Send global regions across (or -2 if blocked face)
401 forAll(patches, patchI)
403 const polyPatch& pp = patches[patchI];
405 if (isA<processorPolyPatch>(pp))
407 labelList myGlobalRegions(pp.size());
409 label faceI = pp.start();
413 if (faceRegion[faceI] < 0)
415 myGlobalRegions[i] = faceRegion[faceI];
419 myGlobalRegions[i] = mergedGlobal
420 [globalRegions.toGlobal(faceRegion[faceI])];
429 refCast<const processorPolyPatch>(pp).neighbProcNo()
432 toProcNbr << myGlobalRegions;
437 // Receive global regions
441 forAll(patches, patchI)
443 const polyPatch& pp = patches[patchI];
445 if (isA<processorPolyPatch>(pp))
447 const processorPolyPatch& procPp =
448 refCast<const processorPolyPatch>(pp);
450 IPstream fromProcNbr(Pstream::blocking, procPp.neighbProcNo());
452 labelList nbrRegions(fromProcNbr);
455 // Compare with my regions to see which get merged.
457 label faceI = pp.start();
463 faceRegion[faceI] < 0
467 if (faceRegion[faceI] != nbrRegions[i])
469 FatalErrorIn("regionSplit::calcRegionSplit(..)")
470 << "On patch:" << pp.name()
472 << " my local region:" << faceRegion[faceI]
473 << " neighbouring region:"
474 << nbrRegions[i] << nl
475 << "Maybe your blockedFaces are not"
476 << " synchronized across coupled faces?"
477 << abort(FatalError);
482 label uncompactGlobal =
483 globalRegions.toGlobal(faceRegion[faceI]);
485 label myGlobal = mergedGlobal[uncompactGlobal];
487 if (myGlobal != nbrRegions[i])
489 label minRegion = min(myGlobal, nbrRegions[i]);
493 Pout<< "Merging region " << myGlobal
494 << " (on proc " << Pstream::myProcNo()
495 << ") and region " << nbrRegions[i]
496 << " (on proc " << procPp.neighbProcNo()
497 << ") into region " << minRegion << endl;
500 mergedGlobal[uncompactGlobal] = minRegion;
501 mergedGlobal[myGlobal] = minRegion;
502 mergedGlobal[nbrRegions[i]] = minRegion;
514 reduce(nMerged, sumOp<label>());
518 Pout<< "nMerged:" << nMerged << endl;
526 // Merge the compacted regions.
527 Pstream::listCombineGather(mergedGlobal, minEqOp<label>());
528 Pstream::listCombineScatter(mergedGlobal);
532 // Compact global regions
533 // ~~~~~~~~~~~~~~~~~~~~~~
535 // All procs will have the same global mergedGlobal region.
536 // There might be gaps in it however so compact.
538 labelList mergedToCompacted(globalRegions.size(), -1);
542 forAll(mergedGlobal, i)
544 label merged = mergedGlobal[i];
546 if (mergedToCompacted[merged] == -1)
548 mergedToCompacted[merged] = compactI++;
554 Pout<< "Compacted down to " << compactI << " regions." << endl;
557 // Renumber cellRegion to be global regions
558 forAll(cellRegion, cellI)
560 label region = cellRegion[cellI];
564 label merged = mergedGlobal[globalRegions.toGlobal(region)];
566 cellRegion[cellI] = mergedToCompacted[merged];
574 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
576 Foam::regionSplit::regionSplit(const polyMesh& mesh)
578 labelList(mesh.nCells(), -1),
580 nRegions_(calcRegionSplit(boolList(0, false), List<labelPair>(0), *this))
584 Foam::regionSplit::regionSplit
586 const polyMesh& mesh,
587 const boolList& blockedFace
590 labelList(mesh.nCells(), -1),
592 nRegions_(calcRegionSplit(blockedFace, List<labelPair>(0), *this))
596 Foam::regionSplit::regionSplit
598 const polyMesh& mesh,
599 const boolList& blockedFace,
600 const List<labelPair>& explicitConnections
603 labelList(mesh.nCells(), -1),
605 nRegions_(calcRegionSplit(blockedFace, explicitConnections, *this))
609 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
612 // ************************************************************************* //