1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "regionSplit.H"
28 #include "cyclicPolyPatch.H"
29 #include "processorPolyPatch.H"
30 #include "globalIndex.H"
31 #include "syncTools.H"
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 defineTypeNameAndDebug(regionSplit, 0);
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 // Handle (non-processor) coupled faces.
45 void Foam::regionSplit::transferCoupledFaceRegion
48 const label otherFaceI,
50 labelList& faceRegion,
51 DynamicList<label>& newChangedFaces
54 if (faceRegion[faceI] >= 0)
56 if (faceRegion[otherFaceI] == -1)
58 faceRegion[otherFaceI] = faceRegion[faceI];
59 newChangedFaces.append(otherFaceI);
61 else if (faceRegion[otherFaceI] == -2)
63 // otherFaceI blocked but faceI is not. Is illegal for coupled
64 // faces, not for explicit connections.
66 else if (faceRegion[otherFaceI] != faceRegion[faceI])
70 "regionSplit::transferCoupledFaceRegion"
71 "(const label, const label, labelList&, labelList&) const"
72 ) << "Problem : coupled face " << faceI
73 << " on patch " << mesh_.boundaryMesh().whichPatch(faceI)
74 << " has region " << faceRegion[faceI]
75 << " but coupled face " << otherFaceI
76 << " has region " << faceRegion[otherFaceI]
78 << "Is your blocked faces specification"
79 << " synchronized across coupled boundaries?"
83 else if (faceRegion[faceI] == -1)
85 if (faceRegion[otherFaceI] >= 0)
87 faceRegion[faceI] = faceRegion[otherFaceI];
88 newChangedFaces.append(faceI);
90 else if (faceRegion[otherFaceI] == -2)
92 // otherFaceI blocked but faceI is not. Is illegal for coupled
93 // faces, not for explicit connections.
99 void Foam::regionSplit::fillSeedMask
101 const List<labelPair>& explicitConnections,
102 labelList& cellRegion,
103 labelList& faceRegion,
104 const label seedCellID,
105 const label markValue
109 cellRegion[seedCellID] = markValue;
112 // Collect faces on seed cell
113 const cell& cFaces = mesh_.cells()[seedCellID];
117 labelList changedFaces(cFaces.size());
121 label faceI = cFaces[i];
123 if (faceRegion[faceI] == -1)
125 faceRegion[faceI] = markValue;
126 changedFaces[nFaces++] = faceI;
129 changedFaces.setSize(nFaces);
132 // Loop over changed faces. MeshWave in small.
134 while (changedFaces.size() > 0)
138 // Pout<< "regionSplit::fillSeedMask : changedFaces:"
139 // << changedFaces.size() << endl;
142 DynamicList<label> changedCells(changedFaces.size());
144 forAll(changedFaces, i)
146 label faceI = changedFaces[i];
148 label own = mesh_.faceOwner()[faceI];
150 if (cellRegion[own] == -1)
152 cellRegion[own] = markValue;
153 changedCells.append(own);
156 if (mesh_.isInternalFace(faceI))
158 label nei = mesh_.faceNeighbour()[faceI];
160 if (cellRegion[nei] == -1)
162 cellRegion[nei] = markValue;
163 changedCells.append(nei);
171 // Pout<< "regionSplit::fillSeedMask : changedCells:"
172 // << changedCells.size() << endl;
175 // Loop over changedCells and collect faces
176 DynamicList<label> newChangedFaces(changedCells.size());
178 forAll(changedCells, i)
180 label cellI = changedCells[i];
182 const cell& cFaces = mesh_.cells()[cellI];
184 forAll(cFaces, cFaceI)
186 label faceI = cFaces[cFaceI];
188 if (faceRegion[faceI] == -1)
190 faceRegion[faceI] = markValue;
191 newChangedFaces.append(faceI);
199 // Pout<< "regionSplit::fillSeedMask : changedFaces before sync:"
200 // << changedFaces.size() << endl;
204 // Check for changes to any locally coupled face.
205 // Global connections are done later.
207 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
209 forAll(patches, patchI)
211 const polyPatch& pp = patches[patchI];
213 if (isA<cyclicPolyPatch>(pp))
215 label faceI = pp.start();
217 label halfSz = pp.size()/2;
219 for (label i = 0; i < halfSz; i++)
221 label otherFaceI = refCast<const cyclicPolyPatch>(pp)
222 .transformGlobalFace(faceI);
224 transferCoupledFaceRegion
236 forAll(explicitConnections, i)
238 transferCoupledFaceRegion
240 explicitConnections[i][0],
241 explicitConnections[i][1],
249 // Pout<< "regionSplit::fillSeedMask : changedFaces after sync:"
250 // << newChangedFaces.size() << endl;
253 changedFaces.transfer(newChangedFaces.shrink());
254 newChangedFaces.clear();
259 Foam::label Foam::regionSplit::calcRegionSplit
261 const boolList& blockedFace,
262 const List<labelPair>& explicitConnections,
264 labelList& cellRegion
269 if (blockedFace.size() > 0)
271 // Check that blockedFace is synced.
272 boolList syncBlockedFace(blockedFace);
273 syncTools::swapFaceList(mesh_, syncBlockedFace, false);
275 forAll(syncBlockedFace, faceI)
277 if (syncBlockedFace[faceI] != blockedFace[faceI])
281 "regionSplit::calcRegionSplit(..)"
282 ) << "Face " << faceI << " not synchronised. My value:"
283 << blockedFace[faceI] << " coupled value:"
284 << syncBlockedFace[faceI]
285 << abort(FatalError);
294 labelList faceRegion(mesh_.nFaces(), -1);
296 if (blockedFace.size() > 0)
298 forAll(blockedFace, faceI)
300 if (blockedFace[faceI])
302 faceRegion[faceI] = -2;
308 // Assign local regions
309 // ~~~~~~~~~~~~~~~~~~~~
311 // Start with region 0
314 label unsetCellI = 0;
318 // Find first unset cell
320 for (; unsetCellI < mesh_.nCells(); unsetCellI++)
322 if (cellRegion[unsetCellI] == -1)
328 if (unsetCellI >= mesh_.nCells())
342 // Current unsetCell has now been handled. Go to next region.
351 forAll(cellRegion, cellI)
353 if (cellRegion[cellI] < 0)
355 FatalErrorIn("regionSplit::calcRegionSplit(..)")
356 << "cell:" << cellI << " region:" << cellRegion[cellI]
357 << abort(FatalError);
361 forAll(faceRegion, faceI)
363 if (faceRegion[faceI] == -1)
365 FatalErrorIn("regionSplit::calcRegionSplit(..)")
366 << "face:" << faceI << " region:" << faceRegion[faceI]
367 << abort(FatalError);
374 // Assign global regions
375 // ~~~~~~~~~~~~~~~~~~~~~
376 // Offset local regions to create unique global regions.
378 globalIndex globalRegions(nRegions);
381 // Merge global regions
382 // ~~~~~~~~~~~~~~~~~~~~
383 // Regions across non-blocked proc patches get merged.
384 // This will set merged global regions to be the min of both.
385 // (this will create gaps in the global region list so they will get
388 // Map from global to merged global
389 labelList mergedGlobal(identity(globalRegions.size()));
392 // See if any regions get merged. Only nessecary for parallel
393 while (Pstream::parRun())
397 Pout<< nl << "-- Starting Iteration --" << endl;
400 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
402 // Send global regions across (or -2 if blocked face)
403 forAll(patches, patchI)
405 const polyPatch& pp = patches[patchI];
407 if (isA<processorPolyPatch>(pp))
409 labelList myGlobalRegions(pp.size());
411 label faceI = pp.start();
415 if (faceRegion[faceI] < 0)
417 myGlobalRegions[i] = faceRegion[faceI];
421 myGlobalRegions[i] = mergedGlobal
422 [globalRegions.toGlobal(faceRegion[faceI])];
431 refCast<const processorPolyPatch>(pp).neighbProcNo()
434 toProcNbr << myGlobalRegions;
439 // Receive global regions
443 forAll(patches, patchI)
445 const polyPatch& pp = patches[patchI];
447 if (isA<processorPolyPatch>(pp))
449 const processorPolyPatch& procPp =
450 refCast<const processorPolyPatch>(pp);
452 IPstream fromProcNbr(Pstream::blocking, procPp.neighbProcNo());
454 labelList nbrRegions(fromProcNbr);
457 // Compare with my regions to see which get merged.
459 label faceI = pp.start();
465 faceRegion[faceI] < 0
469 if (faceRegion[faceI] != nbrRegions[i])
471 FatalErrorIn("regionSplit::calcRegionSplit(..)")
472 << "On patch:" << pp.name()
474 << " my local region:" << faceRegion[faceI]
475 << " neighbouring region:"
476 << nbrRegions[i] << nl
477 << "Maybe your blockedFaces are not"
478 << " synchronized across coupled faces?"
479 << abort(FatalError);
484 label uncompactGlobal =
485 globalRegions.toGlobal(faceRegion[faceI]);
487 label myGlobal = mergedGlobal[uncompactGlobal];
489 if (myGlobal != nbrRegions[i])
491 label minRegion = min(myGlobal, nbrRegions[i]);
495 Pout<< "Merging region " << myGlobal
496 << " (on proc " << Pstream::myProcNo()
497 << ") and region " << nbrRegions[i]
498 << " (on proc " << procPp.neighbProcNo()
499 << ") into region " << minRegion << endl;
502 mergedGlobal[uncompactGlobal] = minRegion;
503 mergedGlobal[myGlobal] = minRegion;
504 mergedGlobal[nbrRegions[i]] = minRegion;
516 reduce(nMerged, sumOp<label>());
520 Pout<< "nMerged:" << nMerged << endl;
528 // Merge the compacted regions.
529 Pstream::listCombineGather(mergedGlobal, minEqOp<label>());
530 Pstream::listCombineScatter(mergedGlobal);
534 // Compact global regions
535 // ~~~~~~~~~~~~~~~~~~~~~~
537 // All procs will have the same global mergedGlobal region.
538 // There might be gaps in it however so compact.
540 labelList mergedToCompacted(globalRegions.size(), -1);
544 forAll(mergedGlobal, i)
546 label merged = mergedGlobal[i];
548 if (mergedToCompacted[merged] == -1)
550 mergedToCompacted[merged] = compactI++;
556 Pout<< "Compacted down to " << compactI << " regions." << endl;
559 // Renumber cellRegion to be global regions
560 forAll(cellRegion, cellI)
562 label region = cellRegion[cellI];
566 label merged = mergedGlobal[globalRegions.toGlobal(region)];
568 cellRegion[cellI] = mergedToCompacted[merged];
576 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
578 Foam::regionSplit::regionSplit(const polyMesh& mesh)
580 labelList(mesh.nCells(), -1),
582 nRegions_(calcRegionSplit(boolList(0, false), List<labelPair>(0), *this))
586 Foam::regionSplit::regionSplit
588 const polyMesh& mesh,
589 const boolList& blockedFace
592 labelList(mesh.nCells(), -1),
594 nRegions_(calcRegionSplit(blockedFace, List<labelPair>(0), *this))
598 Foam::regionSplit::regionSplit
600 const polyMesh& mesh,
601 const boolList& blockedFace,
602 const List<labelPair>& explicitConnections
605 labelList(mesh.nCells(), -1),
607 nRegions_(calcRegionSplit(blockedFace, explicitConnections, *this))
611 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
614 // ************************************************************************* //