ENH: partialWrite: support lagrangian
[OpenFOAM-1.7.x.git] / applications / utilities / parallelProcessing / decomposePar / distributeCells.C
blob5c1a406555c6667b938fa388498bacebcb30c4a4
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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"
28 #include "cpuTime.H"
29 #include "cyclicPolyPatch.H"
30 #include "cellSet.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"))
48     {
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();
56         forAll(pNames, i)
57         {
58             label patchI = patches.findPatchID(pNames[i]);
60             if (patchI == -1)
61             {
62                 FatalErrorIn("domainDecomposition::distributeCells()")
63                     << "Unknown preservePatch " << pNames[i]
64                     << endl << "Valid patches are " << patches.names()
65                     << exit(FatalError);
66             }
68             const polyPatch& pp = patches[patchI];
70             forAll(pp, i)
71             {
72                 sameProcFaces.insert(pp.start() + i);
73             }
74         }
75     }
76     if (decompositionDict_.found("preserveFaceZones"))
77     {
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();
85         forAll(zNames, i)
86         {
87             label zoneI = fZones.findZoneID(zNames[i]);
89             if (zoneI == -1)
90             {
91                 FatalErrorIn("domainDecomposition::distributeCells()")
92                     << "Unknown preserveFaceZone " << zNames[i]
93                     << endl << "Valid faceZones are " << fZones.names()
94                     << exit(FatalError);
95             }
97             const faceZone& fz = fZones[zoneI];
99             forAll(fz, i)
100             {
101                 sameProcFaces.insert(fz[i]);
102             }
103         }
104     }
107     // Construct decomposition method and either do decomposition on
108     // cell centres or on agglomeration
111     autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
112     (
113         decompositionDict_,
114         *this
115     );
117     if (sameProcFaces.empty())
118     {
119         if (decompositionDict_.found("weightField"))
120         {
121             word weightName = decompositionDict_.lookup("weightField");
123             volScalarField weights
124             (
125                 IOobject
126                 (
127                     weightName,
128                     time().timeName(),
129                     *this,
130                     IOobject::MUST_READ,
131                     IOobject::NO_WRITE
132                 ),
133                 *this
134             );
136             cellToProc_ = decomposePtr().decompose
137             (
138                 cellCentres(),
139                 weights.internalField()
140             );
141         }
142         else
143         {
144             cellToProc_ = decomposePtr().decompose(cellCentres());
145         }
146     }
147     else
148     {
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"))
154         {
155             WarningIn("void domainDecomposition::distributeCells()")
156                 << "weightField not supported when agglomerated "
157                 << "decomposition required" << endl;
158         }
160         // Faces where owner and neighbour are not 'connected' (= all except
161         // sameProcFaces)
162         boolList blockedFace(nFaces(), true);
164         forAllConstIter(labelHashSet, sameProcFaces, iter)
165         {
166             blockedFace[iter.key()] = false;
167         }
169         // Connect coupled boundary faces
170         const polyBoundaryMesh& patches =  boundaryMesh();
172         forAll(patches, patchI)
173         {
174             const polyPatch& pp = patches[patchI];
176             if (pp.coupled())
177             {
178                 forAll(pp, i)
179                 {
180                     blockedFace[pp.start()+i] = false;
181                 }
182             }
183         }
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)
202         {
203             label regionI = globalRegion[cellI];
205             if (regionCentres[regionI] == greatPoint)
206             {
207                 regionCentres[regionI] = cellCentres()[cellI];
208             }
209         }
211         // Do decomposition on agglomeration
212         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
213         cellToProc_ = decomposePtr().decompose(globalRegion, regionCentres);
214     }
216     Info<< "\nFinished decomposition in "
217         << decompositionTime.elapsedCpuTime()
218         << " s" << endl;
222 // ************************************************************************* //