kahipDecomp.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2017-2021 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "kahipDecomp.H"
30#include "Time.H"
31#include "PrecisionAdaptor.H"
32
33#include "kaHIP_interface.h"
34
35#include <string>
36#include <map>
37#include <vector>
38
39// Provide a clear error message if we have a severe size mismatch
40// Allow widening, but not narrowing
41
42// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43
44namespace Foam
45{
46 defineTypeNameAndDebug(kahipDecomp, 0);
48 (
49 decompositionMethod,
50 kahipDecomp,
51 dictionary
52 );
53}
54
55
56const Foam::Enum
57<
59>
61({
62 { kahipDecomp::configs::FAST, "fast" },
63 { kahipDecomp::configs::ECO, "eco" },
64 { kahipDecomp::configs::STRONG, "strong" },
65 { kahipDecomp::configs::FASTSOCIAL, "fast-social" },
66 { kahipDecomp::configs::ECOSOCIAL, "eco-social" },
67 { kahipDecomp::configs::STRONGSOCIAL, "strong-social" },
68});
69
70
71// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
72
74(
75 const labelList& adjncy,
76 const labelList& xadj,
77 const List<scalar>& cWeights,
78 labelList& decomp
79) const
80{
81 // Default setup
82 enum configs kahipConfig = configs::FAST;
83 double imbalance = 0.01;
84 int seed = 0;
85 bool verbose = false;
86
87 #if WM_LABEL_SIZE == 64
88 if (xadj.size()-1 > INT_MAX)
89 {
91 << "Cannot decompose " << (xadj.size()-1) << " cells," << nl
92 << "Exceeded integer limit of " << INT_MAX << nl
93 << exit(FatalError);
94 }
95 #endif
96
97 int numCells = max(0, (xadj.size()-1));
98
99 // Addressing
100 ConstPrecisionAdaptor<int, label, List> adjncy_param(adjncy);
101 ConstPrecisionAdaptor<int, label, List> xadj_param(xadj);
102
103 // Output: cell -> processor addressing
104 decomp.resize(numCells);
105 decomp = 0;
106 PrecisionAdaptor<int, label, List> decomp_param(decomp, false);
107
108 // Avoid potential nullptr issues with zero-sized arrays
109 labelList adjncy_dummy, xadj_dummy, decomp_dummy;
110 if (!numCells)
111 {
112 adjncy_dummy.resize(1, 0);
113 adjncy_param.set(adjncy_dummy);
114
115 xadj_dummy.resize(2, 0);
116 xadj_param.set(xadj_dummy);
117
118 decomp_dummy.resize(1, 0);
119 decomp_param.clear(); // Avoid propagating spurious values
120 decomp_param.set(decomp_dummy);
121 }
122
123
124 // Graph
125 // ~~~~~
126
127 // Check for externally provided cellweights and if so initialise weights
128
129 bool hasWeights = !cWeights.empty();
130
131 // Note: min, not gMin since routine runs on master only.
132 const scalar minWeights = hasWeights ? min(cWeights) : scalar(1);
133
134 if (minWeights <= 0)
135 {
136 hasWeights = false;
138 << "Illegal minimum weight " << minWeights
139 << " ... ignoring"
140 << endl;
141 }
142 else if (hasWeights && (cWeights.size() != numCells))
143 {
145 << "Number of cell weights " << cWeights.size()
146 << " does not equal number of cells " << numCells
147 << exit(FatalError);
148 }
149
150 // Cell weights (so on the vertices of the dual)
151 List<int> cellWeights;
152
153 if (hasWeights)
154 {
155 // Convert to integers.
156 cellWeights.resize(cWeights.size());
157 forAll(cellWeights, i)
158 {
159 cellWeights[i] = static_cast<int>
160 (
161 cWeights[i]/minWeights
162 );
163 }
164 }
165
166 configNames.readIfPresent("config", coeffsDict_, kahipConfig);
167 coeffsDict_.readIfPresent("imbalance", imbalance);
168 coeffsDict_.readIfPresent("verbose", verbose);
169
170 Info<< "kahipDecomp :"
171 << " config=" << configNames[kahipConfig]
172 << " imbalance=" << imbalance;
173
174 if (coeffsDict_.readIfPresent("seed", seed))
175 {
176 Info<< " seed=" << seed;
177 }
178
179 // Additional sizing parameters (testing only)
180 std::map<std::string, std::vector<int>> sizingParams;
181
182 List<int> labels;
183 if
184 (
185 coeffsDict_.readIfPresent("hierarchy", labels)
186 && !labels.empty()
187 )
188 {
189 std::vector<int> vec;
190 vec.reserve(labels.size()+1);
191
192 // Verify sizing
193
194 int n = 1;
195 for (const auto val : labels)
196 {
197 n *= val;
198 vec.push_back(val);
199 }
200
201 if (n != nDomains_)
202 {
203 // Size mismatch. Try to correct.
204
205 if (nDomains_ % n)
206 {
208 << "Mismatch in number of processors and "
209 << "hierarchy specified" << flatOutput(labels) << endl;
210
211 vec.clear();
212 }
213 else
214 {
215 // Evenly divisible, add extra hierarchy level
216 vec.push_back(nDomains_ / n);
217 }
218 }
219
220 if (!vec.empty())
221 {
222 sizingParams["hierarchy"] = std::move(vec);
223 Info<< " hierarchy=" << flatOutput(labels);
224 }
225 }
226
227 if
228 (
229 coeffsDict_.readIfPresent("distance", labels)
230 && !labels.empty()
231 )
232 {
233 std::vector<int> vec(labels.size());
234
235 forAll(labels, i)
236 {
237 vec[i] = labels[i];
238 }
239
240 sizingParams["distance"] = std::move(vec);
241 Info<< " distance=" << flatOutput(labels);
242 }
243
244 Info<< endl;
245
246
247 // Number of partitions
248 int nParts = nDomains_;
249
250 // Output: number of cut edges
251 int edgeCut = 0;
252
253
254#if 0 // WIP: #ifdef KAFFPA_CPP_INTERFACE
255 kaffpa_cpp
256 (
257 &numCells, // num vertices in graph
258 (cellWeights.empty() ? nullptr : cellWeights.data()), // vertex wts
259 xadj_param.constCast().data(), // indexing into adjncy
260 nullptr, // edge wts
261 adjncy_param.constCast().data(), // neighbour info
262 &nParts, // nparts
263 &imbalance, // amount of imbalance allowed
264 !verbose, // suppress output
265 seed, // for random
266 int(kahipConfig),
267 &edgeCut, // [output]
268 decomp_param.ref().data(), // [output]
269 sizingParams
270 );
271#else
272 kaffpa
273 (
274 &numCells, // num vertices in graph
275 (cellWeights.empty() ? nullptr : cellWeights.data()), // vertex wts
276 xadj_param.constCast().data(), // indexing into adjncy
277 nullptr, // edge wts
278 adjncy_param.constCast().data(), // neighbour info
279 &nParts, // nparts
280 &imbalance, // amount of imbalance allowed
281 !verbose, // suppress output
282 seed, // for random
283 int(kahipConfig),
284 &edgeCut, // [output]
285 decomp_param.ref().data() // [output]
286 );
287#endif
288
289 return edgeCut;
290}
291
292
293// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
294
296(
297 const dictionary& decompDict,
298 const word& regionName
299)
300:
301 metisLikeDecomp(typeName, decompDict, regionName, selectionType::NULL_DICT)
302{}
303
304
305// ************************************************************************* //
label n
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: Enum.H:61
bool readIfPresent(const word &key, const dictionary &dict, EnumType &val) const
Find an entry if present, and assign to T val.
Definition: EnumI.H:132
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
label nDomains_
Number of domains for the decomposition.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Domain decomposition using KaHIP http://algo2.iti.kit.edu/documents/kahip/.
Definition: kahipDecomp.H:97
virtual label decomposeSerial(const labelList &adjncy, const labelList &xadj, const List< scalar > &cellWeights, labelList &decomp) const
Call kahip with options from dictionary.
configs
The predefined KaHIP configuration types.
Definition: kahipDecomp.H:123
static const Enum< configs > configNames
The selection names for predefined KaHIP configurations.
Definition: kahipDecomp.H:134
const dictionary & coeffsDict_
Coefficients for all derived methods.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
Foam::word regionName(Foam::polyMesh::defaultRegion)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
List< label > labelList
A List of labels.
Definition: List.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:215
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333