1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "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 DynamicList<label>& 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 DynamicList<label> 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 DynamicList<label> 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];
214 isA<cyclicPolyPatch>(pp)
215 && refCast<const cyclicPolyPatch>(pp).owner()
218 // Transfer from neighbourPatch to here or vice versa.
220 const cyclicPolyPatch& cycPatch =
221 refCast<const cyclicPolyPatch>(pp);
223 label faceI = cycPatch.start();
227 label otherFaceI = cycPatch.transformGlobalFace(faceI);
229 transferCoupledFaceRegion
241 forAll(explicitConnections, i)
243 transferCoupledFaceRegion
245 explicitConnections[i][0],
246 explicitConnections[i][1],
254 // Pout<< "regionSplit::fillSeedMask : changedFaces after sync:"
255 // << newChangedFaces.size() << endl;
258 changedFaces.transfer(newChangedFaces);
263 Foam::label Foam::regionSplit::calcRegionSplit
265 const boolList& blockedFace,
266 const List<labelPair>& explicitConnections,
268 labelList& cellRegion
273 if (blockedFace.size())
275 // Check that blockedFace is synced.
276 boolList syncBlockedFace(blockedFace);
277 syncTools::swapFaceList(mesh_, syncBlockedFace);
279 forAll(syncBlockedFace, faceI)
281 if (syncBlockedFace[faceI] != blockedFace[faceI])
285 "regionSplit::calcRegionSplit(..)"
286 ) << "Face " << faceI << " not synchronised. My value:"
287 << blockedFace[faceI] << " coupled value:"
288 << syncBlockedFace[faceI]
289 << abort(FatalError);
298 labelList faceRegion(mesh_.nFaces(), -1);
300 if (blockedFace.size())
302 forAll(blockedFace, faceI)
304 if (blockedFace[faceI])
306 faceRegion[faceI] = -2;
312 // Assign local regions
313 // ~~~~~~~~~~~~~~~~~~~~
315 // Start with region 0
318 label unsetCellI = 0;
322 // Find first unset cell
324 for (; unsetCellI < mesh_.nCells(); unsetCellI++)
326 if (cellRegion[unsetCellI] == -1)
332 if (unsetCellI >= mesh_.nCells())
346 // Current unsetCell has now been handled. Go to next region.
355 forAll(cellRegion, cellI)
357 if (cellRegion[cellI] < 0)
359 FatalErrorIn("regionSplit::calcRegionSplit(..)")
360 << "cell:" << cellI << " region:" << cellRegion[cellI]
361 << abort(FatalError);
365 forAll(faceRegion, faceI)
367 if (faceRegion[faceI] == -1)
369 FatalErrorIn("regionSplit::calcRegionSplit(..)")
370 << "face:" << faceI << " region:" << faceRegion[faceI]
371 << abort(FatalError);
378 // Assign global regions
379 // ~~~~~~~~~~~~~~~~~~~~~
380 // Offset local regions to create unique global regions.
382 globalIndex globalRegions(nRegions);
385 // Merge global regions
386 // ~~~~~~~~~~~~~~~~~~~~
387 // Regions across non-blocked proc patches get merged.
388 // This will set merged global regions to be the min of both.
389 // (this will create gaps in the global region list so they will get
392 // Map from global to merged global
393 labelList mergedGlobal(identity(globalRegions.size()));
396 // See if any regions get merged. Only nessecary for parallel
397 while (Pstream::parRun())
401 Pout<< nl << "-- Starting Iteration --" << endl;
404 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
406 // Send global regions across (or -2 if blocked face)
407 forAll(patches, patchI)
409 const polyPatch& pp = patches[patchI];
411 if (isA<processorPolyPatch>(pp))
413 labelList myGlobalRegions(pp.size());
415 label faceI = pp.start();
419 if (faceRegion[faceI] < 0)
421 myGlobalRegions[i] = faceRegion[faceI];
425 myGlobalRegions[i] = mergedGlobal
426 [globalRegions.toGlobal(faceRegion[faceI])];
435 refCast<const processorPolyPatch>(pp).neighbProcNo()
438 toProcNbr << myGlobalRegions;
443 // Receive global regions
447 forAll(patches, patchI)
449 const polyPatch& pp = patches[patchI];
451 if (isA<processorPolyPatch>(pp))
453 const processorPolyPatch& procPp =
454 refCast<const processorPolyPatch>(pp);
456 IPstream fromProcNbr(Pstream::blocking, procPp.neighbProcNo());
458 labelList nbrRegions(fromProcNbr);
461 // Compare with my regions to see which get merged.
463 label faceI = pp.start();
469 faceRegion[faceI] < 0
473 if (faceRegion[faceI] != nbrRegions[i])
475 FatalErrorIn("regionSplit::calcRegionSplit(..)")
476 << "On patch:" << pp.name()
478 << " my local region:" << faceRegion[faceI]
479 << " neighbouring region:"
480 << nbrRegions[i] << nl
481 << "Maybe your blockedFaces are not"
482 << " synchronized across coupled faces?"
483 << abort(FatalError);
488 label uncompactGlobal =
489 globalRegions.toGlobal(faceRegion[faceI]);
491 label myGlobal = mergedGlobal[uncompactGlobal];
493 if (myGlobal != nbrRegions[i])
495 label minRegion = min(myGlobal, nbrRegions[i]);
499 Pout<< "Merging region " << myGlobal
500 << " (on proc " << Pstream::myProcNo()
501 << ") and region " << nbrRegions[i]
502 << " (on proc " << procPp.neighbProcNo()
503 << ") into region " << minRegion << endl;
506 mergedGlobal[uncompactGlobal] = minRegion;
507 mergedGlobal[myGlobal] = minRegion;
508 mergedGlobal[nbrRegions[i]] = minRegion;
520 reduce(nMerged, sumOp<label>());
524 Pout<< "nMerged:" << nMerged << endl;
532 // Merge the compacted regions.
533 Pstream::listCombineGather(mergedGlobal, minEqOp<label>());
534 Pstream::listCombineScatter(mergedGlobal);
538 // Compact global regions
539 // ~~~~~~~~~~~~~~~~~~~~~~
541 // All procs will have the same global mergedGlobal region.
542 // There might be gaps in it however so compact.
544 labelList mergedToCompacted(globalRegions.size(), -1);
548 forAll(mergedGlobal, i)
550 label merged = mergedGlobal[i];
552 if (mergedToCompacted[merged] == -1)
554 mergedToCompacted[merged] = compactI++;
560 Pout<< "Compacted down to " << compactI << " regions." << endl;
563 // Renumber cellRegion to be global regions
564 forAll(cellRegion, cellI)
566 label region = cellRegion[cellI];
570 label merged = mergedGlobal[globalRegions.toGlobal(region)];
572 cellRegion[cellI] = mergedToCompacted[merged];
580 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
582 Foam::regionSplit::regionSplit(const polyMesh& mesh)
584 labelList(mesh.nCells(), -1),
586 nRegions_(calcRegionSplit(boolList(0, false), List<labelPair>(0), *this))
590 Foam::regionSplit::regionSplit
592 const polyMesh& mesh,
593 const boolList& blockedFace
596 labelList(mesh.nCells(), -1),
598 nRegions_(calcRegionSplit(blockedFace, List<labelPair>(0), *this))
602 Foam::regionSplit::regionSplit
604 const polyMesh& mesh,
605 const boolList& blockedFace,
606 const List<labelPair>& explicitConnections
609 labelList(mesh.nCells(), -1),
611 nRegions_(calcRegionSplit(blockedFace, explicitConnections, *this))
615 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
618 // ************************************************************************* //