1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 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
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 "domainDecomposition.H"
27 #include "decompositionMethod.H"
29 #include "cyclicPolyPatch.H"
31 #include "regionSplit.H"
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 void domainDecomposition::distributeCells()
37 Info<< "\nCalculating distribution of cells" << endl;
39 cpuTime decompositionTime;
42 // See if any faces need to have owner and neighbour on same processor
43 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45 labelHashSet sameProcFaces;
47 if (decompositionDict_.found("preservePatches"))
49 wordList pNames(decompositionDict_.lookup("preservePatches"));
51 Info<< "Keeping owner of faces in patches " << pNames
52 << " on same processor. This only makes sense for cyclics." << endl;
54 const polyBoundaryMesh& patches = boundaryMesh();
58 label patchI = patches.findPatchID(pNames[i]);
62 FatalErrorIn("domainDecomposition::distributeCells()")
63 << "Unknown preservePatch " << pNames[i]
64 << endl << "Valid patches are " << patches.names()
68 const polyPatch& pp = patches[patchI];
72 sameProcFaces.insert(pp.start() + i);
76 if (decompositionDict_.found("preserveFaceZones"))
78 wordList zNames(decompositionDict_.lookup("preserveFaceZones"));
80 Info<< "Keeping owner and neighbour of faces in zones " << zNames
81 << " on same processor" << endl;
83 const faceZoneMesh& fZones = faceZones();
87 label zoneI = fZones.findZoneID(zNames[i]);
91 FatalErrorIn("domainDecomposition::distributeCells()")
92 << "Unknown preserveFaceZone " << zNames[i]
93 << endl << "Valid faceZones are " << fZones.names()
97 const faceZone& fz = fZones[zoneI];
101 sameProcFaces.insert(fz[i]);
107 // Construct decomposition method and either do decomposition on
108 // cell centres or on agglomeration
111 autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
117 if (sameProcFaces.empty())
119 if (decompositionDict_.found("weightField"))
121 word weightName = decompositionDict_.lookup("weightField");
123 volScalarField weights
136 cellToProc_ = decomposePtr().decompose
139 weights.internalField()
144 cellToProc_ = decomposePtr().decompose(cellCentres());
149 Info<< "Selected " << sameProcFaces.size()
150 << " faces whose owner and neighbour cell should be kept on the"
151 << " same processor" << endl;
153 if (decompositionDict_.found("weightField"))
155 WarningIn("void domainDecomposition::distributeCells()")
156 << "weightField not supported when agglomerated "
157 << "decomposition required" << endl;
160 // Faces where owner and neighbour are not 'connected' (= all except
162 boolList blockedFace(nFaces(), true);
164 forAllConstIter(labelHashSet, sameProcFaces, iter)
166 blockedFace[iter.key()] = false;
169 // Connect coupled boundary faces
170 const polyBoundaryMesh& patches = boundaryMesh();
172 forAll(patches, patchI)
174 const polyPatch& pp = patches[patchI];
180 blockedFace[pp.start()+i] = false;
185 // Determine global regions, separated by blockedFaces
186 regionSplit globalRegion(*this, blockedFace);
189 // Determine region cell centres
190 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192 // This just takes the first cell in the region. Otherwise the problem
193 // is with cyclics - if we'd average the region centre might be
194 // somewhere in the middle of the domain which might not be anywhere
195 // near any of the cells.
197 const point greatPoint(GREAT, GREAT, GREAT);
199 pointField regionCentres(globalRegion.nRegions(), greatPoint);
201 forAll(globalRegion, cellI)
203 label regionI = globalRegion[cellI];
205 if (regionCentres[regionI] == greatPoint)
207 regionCentres[regionI] = cellCentres()[cellI];
211 // Do decomposition on agglomeration
212 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213 cellToProc_ = decomposePtr().decompose(globalRegion, regionCentres);
216 Info<< "\nFinished decomposition in "
217 << decompositionTime.elapsedCpuTime()
222 // ************************************************************************* //