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 "multiLevelDecomp.H"
27 #include "addToRunTimeSelectionTable.H"
29 #include "globalIndex.H"
30 #include "mapDistribute.H"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 defineTypeNameAndDebug(multiLevelDecomp, 0);
38 addToRunTimeSelectionTable
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 // Given a subset of cells determine the new global indices. The problem
50 // is in the cells from neighbouring processors which need to be renumbered.
51 void Foam::multiLevelDecomp::subsetGlobalCellCells
55 const labelList& dist,
57 const labelListList& cellCells,
59 labelListList& subCellCells,
60 labelList& cutConnections
63 // Determine new index for cells by inverting subset
64 labelList oldToNew(invert(cellCells.size(), set));
66 globalIndex globalCells(cellCells.size());
68 // Subset locally the elements for which I have data
69 subCellCells = UIndirectList<labelList>(cellCells, set);
71 // Get new indices for neighbouring processors
72 List<Map<label> > compactMap;
73 mapDistribute map(globalCells, subCellCells, compactMap);
74 map.distribute(oldToNew);
75 labelList allDist(dist);
76 map.distribute(allDist);
79 // oldToNew : the locally-compact numbering of all our cellCells. -1 if
80 // cellCell is not in set.
81 // allDist : destination domain for all our cellCells
82 // subCellCells : indexes into oldToNew and allDist
84 // Globally compact numbering for cells in set.
85 globalIndex globalSubCells(set.size());
87 // Now subCellCells contains indices into oldToNew which are the
88 // new locations of the neighbouring cells.
90 cutConnections.setSize(nDomains);
93 forAll(subCellCells, subCellI)
95 labelList& cCells = subCellCells[subCellI];
97 // Keep the connections to valid mapped cells
101 // Get locally-compact cell index of neighbouring cell
102 label nbrCellI = oldToNew[cCells[i]];
105 cutConnections[allDist[cCells[i]]]++;
109 // Reconvert local cell index into global one
111 // Get original neighbour
112 label cellI = set[subCellI];
113 label oldNbrCellI = cellCells[cellI][i];
114 // Get processor from original neighbour
115 label procI = globalCells.whichProcID(oldNbrCellI);
116 // Convert into global compact numbering
117 cCells[newI++] = globalSubCells.toGlobal(procI, nbrCellI);
120 cCells.setSize(newI);
125 void Foam::multiLevelDecomp::decompose
127 const labelListList& pointPoints,
128 const pointField& points,
129 const scalarField& pointWeights,
130 const labelList& pointMap, // map back to original points
133 labelField& finalDecomp
138 methods_[levelI].decompose
148 label orig = pointMap[i];
149 finalDecomp[orig] += dist[i];
152 if (levelI != methods_.size()-1)
156 // Determine points per domain
157 label n = methods_[levelI].nDomains();
158 labelListList domainToPoints(invertOneToMany(n, dist));
160 // 'Make space' for new levels of decomposition
161 finalDecomp *= methods_[levelI+1].nDomains();
163 // Extract processor+local index from point-point addressing
164 if (debug && Pstream::master())
166 Pout<< "Decomposition at level " << levelI << " :" << endl;
169 for (label domainI = 0; domainI < n; domainI++)
171 // Extract elements for current domain
172 const labelList domainPoints(findIndices(dist, domainI));
174 // Subset point-wise data.
175 pointField subPoints(points, domainPoints);
176 scalarField subWeights(pointWeights, domainPoints);
177 labelList subPointMap(UIndirectList<label>(pointMap, domainPoints));
178 // Subset point-point addressing (adapt global numbering)
179 labelListList subPointPoints;
180 labelList nOutsideConnections;
181 subsetGlobalCellCells
194 label nPoints = returnReduce(domainPoints.size(), plusOp<label>());
195 Pstream::listCombineGather(nOutsideConnections, plusEqOp<label>());
196 Pstream::listCombineScatter(nOutsideConnections);
199 forAll(nOutsideConnections, i)
201 if (nOutsideConnections[i] > 0)
204 nFaces += nOutsideConnections[i];
209 if (debug && Pstream::master())
211 Pout<< " Domain " << domainI << nl
212 << " Number of cells = " << nPoints << nl
213 << " Number of inter-domain patches = " << nPatches
215 << " Number of inter-domain faces = " << nFaces << nl
217 oldPrefix = Pout.prefix();
218 Pout.prefix() = " " + oldPrefix;
231 if (debug && Pstream::master())
233 Pout.prefix() = oldPrefix;
240 // Do straight decompose of two levels
241 label nNext = methods_[levelI+1].nDomains();
242 label nTotal = n*nNext;
244 // Retrieve original level0 dictionary and modify number of domains
245 dictionary::const_iterator iter =
246 decompositionDict_.subDict(typeName + "Coeffs").begin();
247 dictionary myDict = iter().dict();
248 myDict.set("numberOfSubdomains", nTotal);
250 if (debug && Pstream::master())
252 Pout<< "Reference decomposition with " << myDict << " :"
256 autoPtr<decompositionMethod> method0 = decompositionMethod::New
270 for (label blockI = 0; blockI < n; blockI++)
272 // Count the number inbetween blocks of nNext size
275 labelList nOutsideConnections(n, 0);
276 forAll(pointPoints, pointI)
278 if ((dist[pointI] / nNext) == blockI)
282 const labelList& pPoints = pointPoints[pointI];
286 label distBlockI = dist[pPoints[i]] / nNext;
287 if (distBlockI != blockI)
289 nOutsideConnections[distBlockI]++;
295 reduce(nPoints, plusOp<label>());
296 Pstream::listCombineGather
301 Pstream::listCombineScatter(nOutsideConnections);
304 forAll(nOutsideConnections, i)
306 if (nOutsideConnections[i] > 0)
309 nFaces += nOutsideConnections[i];
313 if (debug && Pstream::master())
315 Pout<< " Domain " << blockI << nl
316 << " Number of cells = " << nPoints << nl
317 << " Number of inter-domain patches = "
319 << " Number of inter-domain faces = " << nFaces
328 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
330 Foam::multiLevelDecomp::multiLevelDecomp(const dictionary& decompositionDict)
332 decompositionMethod(decompositionDict),
333 methodsDict_(decompositionDict_.subDict(typeName + "Coeffs"))
335 methods_.setSize(methodsDict_.size());
337 forAllConstIter(dictionary, methodsDict_, iter)
339 methods_.set(i++, decompositionMethod::New(iter().dict()));
343 Info<< "decompositionMethod " << type() << " :" << endl;
346 Info<< " level " << i << " decomposing with " << methods_[i].type()
347 << " into " << methods_[i].nDomains() << " subdomains." << endl;
349 n *= methods_[i].nDomains();
354 FatalErrorIn("multiLevelDecomp::multiLevelDecomp(const dictionary&)")
355 << "Top level decomposition specifies " << nDomains()
356 << " domains which is not equal to the product of"
357 << " all sub domains " << n
363 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
365 bool Foam::multiLevelDecomp::parallelAware() const
369 if (!methods_[i].parallelAware())
378 Foam::labelList Foam::multiLevelDecomp::decompose
380 const polyMesh& mesh,
381 const pointField& cc,
382 const scalarField& cWeights
385 CompactListList<label> cellCells;
386 calcCellCells(mesh, identity(cc.size()), cc.size(), cellCells);
388 labelField finalDecomp(cc.size(), 0);
389 labelList cellMap(identity(cc.size()));
396 cellMap, // map back to original cells
406 Foam::labelList Foam::multiLevelDecomp::decompose
408 const labelListList& globalPointPoints,
409 const pointField& points,
410 const scalarField& pointWeights
413 labelField finalDecomp(points.size(), 0);
414 labelList pointMap(identity(points.size()));
421 pointMap, // map back to original points
431 // ************************************************************************* //