1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. 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 Foam::label Foam::metisDecomp::decompose
58 const List<int>& adjncy,
59 const List<int>& xadj,
60 const scalarField& cWeights,
61 List<int>& finalDecomp
64 // Method of decomposition
65 // recursive: multi-level recursive bisection (default)
66 // k-way: multi-level k-way
69 int numCells = xadj.size()-1;
71 // decomposition options. 0 = use defaults
72 idx_t options[METIS_NOPTIONS];
73 METIS_SetDefaultOptions(options);
75 // processor weights initialised with no size, only used if specified in
76 // a file - use the data type that metis expects here
77 Field<real_t> processorWeights;
79 // cell weights (so on the vertices of the dual)
80 List<int> cellWeights;
82 // face weights (so on the edges of the dual)
83 List<int> faceWeights;
86 // Check for externally provided cellweights and if so initialise weights
87 scalar minWeights = gMin(cWeights);
88 if (cWeights.size() > 0)
94 "metisDecomp::decompose"
95 "(const pointField&, const scalarField&)"
96 ) << "Illegal minimum weight " << minWeights
100 if (cWeights.size() != numCells)
104 "metisDecomp::decompose"
105 "(const pointField&, const scalarField&)"
106 ) << "Number of cell weights " << cWeights.size()
107 << " does not equal number of cells " << numCells
110 // Convert to integers.
111 cellWeights.setSize(cWeights.size());
112 forAll(cellWeights, i)
114 cellWeights[i] = int(cWeights[i]/minWeights);
119 // Check for user supplied weights and decomp options
120 if (decompositionDict_.found("metisCoeffs"))
122 const dictionary& metisCoeffs =
123 decompositionDict_.subDict("metisCoeffs");
126 if (metisCoeffs.readIfPresent("method", method))
128 if (method != "recursive" && method != "k-way")
130 FatalErrorIn("metisDecomp::decompose()")
131 << "Method " << method
132 << " in metisCoeffs in dictionary : "
133 << decompositionDict_.name()
134 << " should be 'recursive' or 'k-way'"
138 Info<< "metisDecomp : Using Metis method " << method
143 if (metisCoeffs.readIfPresent("options", mOptions))
145 if (mOptions.size() != METIS_NOPTIONS)
147 FatalErrorIn("metisDecomp::decompose()")
148 << "Number of options in metisCoeffs in dictionary : "
149 << decompositionDict_.name()
150 << " should be " << METIS_NOPTIONS
156 options[i] = mOptions[i];
159 Info<< "metisDecomp : Using Metis options " << mOptions
163 if (metisCoeffs.readIfPresent("processorWeights", processorWeights))
165 processorWeights /= sum(processorWeights);
167 if (processorWeights.size() != nProcessors_)
169 FatalErrorIn("metisDecomp::decompose(const pointField&)")
170 << "Number of processor weights "
171 << processorWeights.size()
172 << " does not equal number of domains " << nProcessors_
177 if (metisCoeffs.readIfPresent("cellWeightsFile", weightsFile))
179 Info<< "metisDecomp : Using cell-based weights." << endl;
181 IOList<int> cellIOWeights
186 mesh_.time().timeName(),
192 cellWeights.transfer(cellIOWeights);
194 if (cellWeights.size() != xadj.size()-1)
196 FatalErrorIn("metisDecomp::decompose(const pointField&)")
197 << "Number of cell weights " << cellWeights.size()
198 << " does not equal number of cells " << xadj.size()-1
204 int nProcs = nProcessors_;
206 // output: cell -> processor addressing
207 finalDecomp.setSize(numCells);
209 // output: number of cut edges
212 // Vertex weight info
214 int* adjwgtPtr = NULL;
216 if (cellWeights.size())
218 vwgtPtr = cellWeights.begin();
220 if (faceWeights.size())
222 adjwgtPtr = faceWeights.begin();
227 if (method == "recursive")
229 METIS_PartGraphRecursive
231 &numCells, // num vertices in graph
233 const_cast<List<int>&>(xadj).begin(), // indexing into adjncy
234 const_cast<List<int>&>(adjncy).begin(), // neighbour info
235 vwgtPtr, // vertexweights
237 adjwgtPtr, // no edgeweights
239 processorWeights.begin(),
250 &numCells, // num vertices in graph
252 const_cast<List<int>&>(xadj).begin(), // indexing into adjncy
253 const_cast<List<int>&>(adjncy).begin(), // neighbour info
254 vwgtPtr, // vertexweights
256 adjwgtPtr, // no edgeweights
258 processorWeights.begin(),
270 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
272 Foam::metisDecomp::metisDecomp
274 const dictionary& decompositionDict,
278 decompositionMethod(decompositionDict),
283 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
285 Foam::labelList Foam::metisDecomp::decompose
287 const pointField& points,
288 const scalarField& pointWeights
291 if (points.size() != mesh_.nCells())
295 "metisDecomp::decompose(const pointField&,const scalarField&)"
296 ) << "Can use this decomposition method only for the whole mesh"
298 << "and supply one coordinate (cellCentre) for every cell." << endl
299 << "The number of coordinates " << points.size() << endl
300 << "The number of cells in the mesh " << mesh_.nCells()
313 // Decompose using default weights
314 List<int> finalDecomp;
315 decompose(adjncy, xadj, pointWeights, finalDecomp);
317 // Copy back to labelList
318 labelList decomp(finalDecomp.size());
321 decomp[i] = finalDecomp[i];
327 Foam::labelList Foam::metisDecomp::decompose
329 const labelList& fineToCoarse,
330 const pointField& coarsePoints,
331 const scalarField& coarseWeights
334 if (fineToCoarse.size() != mesh_.nCells())
338 "metisDecomp::decompose"
339 "(const labelList&, const pointField&, const scalarField&)"
340 ) << "Size of cell-to-coarse map " << fineToCoarse.size()
341 << " differs from number of cells in mesh " << mesh_.nCells()
345 // Make Metis CSR (Compressed Storage Format) storage
346 // adjncy : contains neighbours (= edges in graph)
347 // xadj(celli) : start of information in adjncy for celli
351 // Get cellCells on coarse mesh.
352 labelListList cellCells;
361 calcCSR(cellCells, adjncy, xadj);
364 // Decompose using default weights
365 List<int> finalDecomp;
366 decompose(adjncy, xadj, coarseWeights, finalDecomp);
369 // Rework back into decomposition for original mesh_
370 labelList fineDistribution(fineToCoarse.size());
372 forAll(fineDistribution, i)
374 fineDistribution[i] = finalDecomp[fineToCoarse[i]];
377 return fineDistribution;
381 Foam::labelList Foam::metisDecomp::decompose
383 const labelListList& globalCellCells,
384 const pointField& cc,
385 const scalarField& cWeights
388 if (cc.size() != globalCellCells.size())
392 "metisDecomp::decompose"
393 "(const pointField&, const labelListList&, const scalarField&)"
394 ) << "Inconsistent number of cells (" << globalCellCells.size()
395 << ") and number of cell centres (" << cc.size()
396 << ")." << exit(FatalError);
400 // Make Metis CSR (Compressed Storage Format) storage
401 // adjncy : contains neighbours (= edges in graph)
402 // xadj(celli) : start of information in adjncy for celli
406 calcCSR(globalCellCells, adjncy, xadj);
408 // Decompose using default weights
409 List<int> finalDecomp;
410 decompose(adjncy, xadj, cWeights, finalDecomp);
412 // Copy back to labelList
413 labelList decomp(finalDecomp.size());
417 decomp[i] = finalDecomp[i];
424 // ************************************************************************* //