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 "metisDecomp.H"
27 #include "addToRunTimeSelectionTable.H"
28 #include "floatScalar.H"
30 #include "scotchDecomp.H"
34 #define OMPI_SKIP_MPICXX
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(metisDecomp, 0);
45 addToRunTimeSelectionTable
54 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 // Call Metis with options from dictionary.
57 Foam::label Foam::metisDecomp::decompose
59 const List<int>& adjncy,
60 const List<int>& xadj,
61 const scalarField& cWeights,
63 List<int>& finalDecomp
69 // Method of decomposition
70 // recursive: multi-level recursive bisection (default)
71 // k-way: multi-level k-way
74 int numCells = xadj.size()-1;
76 // decomposition options. 0 = use defaults
77 List<int> options(5, 0);
79 // processor weights initialised with no size, only used if specified in
81 Field<floatScalar> processorWeights;
83 // cell weights (so on the vertices of the dual)
84 List<int> cellWeights;
86 // face weights (so on the edges of the dual)
87 List<int> faceWeights;
90 // Check for externally provided cellweights and if so initialise weights
91 scalar minWeights = gMin(cWeights);
92 if (cWeights.size() > 0)
98 "metisDecomp::decompose"
99 "(const pointField&, const scalarField&)"
100 ) << "Illegal minimum weight " << minWeights
104 if (cWeights.size() != numCells)
108 "metisDecomp::decompose"
109 "(const pointField&, const scalarField&)"
110 ) << "Number of cell weights " << cWeights.size()
111 << " does not equal number of cells " << numCells
114 // Convert to integers.
115 cellWeights.setSize(cWeights.size());
116 forAll(cellWeights, i)
118 cellWeights[i] = int(cWeights[i]/minWeights);
123 // Check for user supplied weights and decomp options
124 if (decompositionDict_.found("metisCoeffs"))
126 const dictionary& metisCoeffs =
127 decompositionDict_.subDict("metisCoeffs");
130 if (metisCoeffs.readIfPresent("method", method))
132 if (method != "recursive" && method != "k-way")
134 FatalErrorIn("metisDecomp::decompose()")
135 << "Method " << method << " in metisCoeffs in dictionary : "
136 << decompositionDict_.name()
137 << " should be 'recursive' or 'k-way'"
141 Info<< "metisDecomp : Using Metis method " << method
145 if (metisCoeffs.readIfPresent("options", options))
147 if (options.size() != 5)
149 FatalErrorIn("metisDecomp::decompose()")
150 << "Number of options in metisCoeffs in dictionary : "
151 << decompositionDict_.name()
156 Info<< "metisDecomp : Using Metis options " << options
160 if (metisCoeffs.readIfPresent("processorWeights", processorWeights))
162 processorWeights /= sum(processorWeights);
164 if (processorWeights.size() != nProcessors_)
166 FatalErrorIn("metisDecomp::decompose(const pointField&)")
167 << "Number of processor weights "
168 << processorWeights.size()
169 << " does not equal number of domains " << nProcessors_
174 if (metisCoeffs.readIfPresent("cellWeightsFile", weightsFile))
176 Info<< "metisDecomp : Using cell-based weights." << endl;
178 IOList<int> cellIOWeights
183 mesh_.time().timeName(),
189 cellWeights.transfer(cellIOWeights);
191 if (cellWeights.size() != xadj.size()-1)
193 FatalErrorIn("metisDecomp::decompose(const pointField&)")
194 << "Number of cell weights " << cellWeights.size()
195 << " does not equal number of cells " << xadj.size()-1
201 int nProcs = nProcessors_;
203 // output: cell -> processor addressing
204 finalDecomp.setSize(numCells);
206 // output: number of cut edges
209 // Vertex weight info
212 int* adjwgtPtr = NULL;
214 if (cellWeights.size())
216 vwgtPtr = cellWeights.begin();
217 wgtFlag += 2; // Weights on vertices
219 if (faceWeights.size())
221 adjwgtPtr = faceWeights.begin();
222 wgtFlag += 1; // Weights on edges
225 if (method == "recursive")
227 if (processorWeights.size())
229 METIS_WPartGraphRecursive
231 &numCells, // num vertices in graph
232 const_cast<List<int>&>(xadj).begin(), // indexing into adjncy
233 const_cast<List<int>&>(adjncy).begin(), // neighbour info
234 vwgtPtr, // vertexweights
235 adjwgtPtr, // no edgeweights
239 processorWeights.begin(),
247 METIS_PartGraphRecursive
249 &numCells, // num vertices in graph
250 const_cast<List<int>&>(xadj).begin(), // indexing into adjncy
251 const_cast<List<int>&>(adjncy).begin(), // neighbour info
252 vwgtPtr, // vertexweights
253 adjwgtPtr, // no edgeweights
265 if (processorWeights.size())
269 &numCells, // num vertices in graph
270 const_cast<List<int>&>(xadj).begin(), // indexing into adjncy
271 const_cast<List<int>&>(adjncy).begin(), // neighbour info
272 vwgtPtr, // vertexweights
273 adjwgtPtr, // no edgeweights
277 processorWeights.begin(),
287 &numCells, // num vertices in graph
288 const_cast<List<int>&>(xadj).begin(), // indexing into adjncy
289 const_cast<List<int>&>(adjncy).begin(), // neighbour info
290 vwgtPtr, // vertexweights
291 adjwgtPtr, // no edgeweights
306 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
308 Foam::metisDecomp::metisDecomp
310 const dictionary& decompositionDict,
314 decompositionMethod(decompositionDict),
319 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
321 Foam::labelList Foam::metisDecomp::decompose
323 const pointField& points,
324 const scalarField& pointWeights
327 if (points.size() != mesh_.nCells())
331 "metisDecomp::decompose(const pointField&,const scalarField&)"
332 ) << "Can use this decomposition method only for the whole mesh"
334 << "and supply one coordinate (cellCentre) for every cell." << endl
335 << "The number of coordinates " << points.size() << endl
336 << "The number of cells in the mesh " << mesh_.nCells()
342 scotchDecomp::calcCSR
349 // Decompose using default weights
350 List<int> finalDecomp;
351 decompose(adjncy, xadj, pointWeights, finalDecomp);
353 // Copy back to labelList
354 labelList decomp(finalDecomp.size());
357 decomp[i] = finalDecomp[i];
363 Foam::labelList Foam::metisDecomp::decompose
365 const labelList& agglom,
366 const pointField& agglomPoints,
367 const scalarField& agglomWeights
370 if (agglom.size() != mesh_.nCells())
374 "metisDecomp::decompose"
375 "(const labelList&, const pointField&, const scalarField&)"
376 ) << "Size of cell-to-coarse map " << agglom.size()
377 << " differs from number of cells in mesh " << mesh_.nCells()
381 // Make Metis CSR (Compressed Storage Format) storage
382 // adjncy : contains neighbours (= edges in graph)
383 // xadj(celli) : start of information in adjncy for celli
387 // Get cellCells on coarse mesh.
388 labelListList cellCells;
397 scotchDecomp::calcCSR(cellCells, adjncy, xadj);
400 // Decompose using default weights
401 List<int> finalDecomp;
402 decompose(adjncy, xadj, agglomWeights, finalDecomp);
405 // Rework back into decomposition for original mesh_
406 labelList fineDistribution(agglom.size());
408 forAll(fineDistribution, i)
410 fineDistribution[i] = finalDecomp[agglom[i]];
413 return fineDistribution;
417 Foam::labelList Foam::metisDecomp::decompose
419 const labelListList& globalCellCells,
420 const pointField& cellCentres,
421 const scalarField& cellWeights
424 if (cellCentres.size() != globalCellCells.size())
428 "metisDecomp::decompose"
429 "(const pointField&, const labelListList&, const scalarField&)"
430 ) << "Inconsistent number of cells (" << globalCellCells.size()
431 << ") and number of cell centres (" << cellCentres.size()
432 << ")." << exit(FatalError);
436 // Make Metis CSR (Compressed Storage Format) storage
437 // adjncy : contains neighbours (= edges in graph)
438 // xadj(celli) : start of information in adjncy for celli
442 scotchDecomp::calcCSR(globalCellCells, adjncy, xadj);
445 // Decompose using default weights
446 List<int> finalDecomp;
447 decompose(adjncy, xadj, cellWeights, finalDecomp);
449 // Copy back to labelList
450 labelList decomp(finalDecomp.size());
453 decomp[i] = finalDecomp[i];
459 // ************************************************************************* //