Loading...
Searching...
No Matches
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-2023 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"
32#include <map>
33#include <string>
34#include <vector>
35
36// Probably not needed, but in case we pickup parhip_interface.h
37#ifndef MPICH_SKIP_MPICXX
38#define MPICH_SKIP_MPICXX
39#endif
40#ifndef OMPI_SKIP_MPICXX
41#define OMPI_SKIP_MPICXX
42#endif
43
44#include "kaHIP_interface.h"
45
46// Provide a clear error message if we have a severe size mismatch
47// Allow widening, but not narrowing
48
49// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
50
51namespace Foam
52{
55 (
59 );
60}
61
62
63const Foam::Enum
64<
66>
68({
69 { kahipDecomp::configs::FAST, "fast" },
70 { kahipDecomp::configs::ECO, "eco" },
71 { kahipDecomp::configs::STRONG, "strong" },
72 { kahipDecomp::configs::FASTSOCIAL, "fast-social" },
74 { kahipDecomp::configs::STRONGSOCIAL, "strong-social" },
75});
76
77
78// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
79
81(
82 const labelList& adjncy,
83 const labelList& xadj,
84 const List<scalar>& cWeights,
85 labelList& decomp
86) const
87{
88 // Default setup
89 enum configs kahipConfig = configs::FAST;
90 double imbalance = 0.01;
91 int seed = 0;
92 bool verbose = false;
93
94 #if WM_LABEL_SIZE == 64
95 if (xadj.size()-1 > INT_MAX)
96 {
98 << "Cannot decompose " << (xadj.size()-1) << " cells," << nl
99 << "Exceeded integer limit of " << INT_MAX << nl
100 << exit(FatalError);
101 }
102 #endif
103
104 int numCells = Foam::max(0, (xadj.size()-1));
105
106 // Addressing
107 ConstPrecisionAdaptor<int, label, List> adjncy_param(adjncy);
108 ConstPrecisionAdaptor<int, label, List> xadj_param(xadj);
109
110 // Output: cell -> processor addressing
111 decomp.resize_nocopy(numCells);
112 decomp = 0;
113 PrecisionAdaptor<int, label, List> decomp_param(decomp, false);
114
115 // Avoid potential nullptr issues with zero-sized arrays
116 labelList adjncy_dummy, xadj_dummy, decomp_dummy;
117 if (!numCells)
118 {
119 adjncy_dummy.resize(1, 0);
120 adjncy_param.set(adjncy_dummy);
121
122 xadj_dummy.resize(2, 0);
123 xadj_param.set(xadj_dummy);
124
125 decomp_dummy.resize(1, 0);
126 decomp_param.clear(); // Avoid propagating spurious values
127 decomp_param.set(decomp_dummy);
128 }
129
130
131 // Graph
132 // ~~~~~
133
134 // Check for externally provided cellweights and if so initialise weights
135
136 bool hasWeights = !cWeights.empty();
137
138 // Note: min, not gMin since routine runs on master only.
139 const scalar minWeights = hasWeights ? min(cWeights) : scalar(1);
140
141 if (minWeights <= 0)
142 {
143 hasWeights = false;
145 << "Illegal minimum weight " << minWeights
146 << " ... ignoring"
147 << endl;
148 }
149 else if (hasWeights && (cWeights.size() != numCells))
150 {
151 FatalErrorInFunction
152 << "Number of weights (" << cWeights.size()
153 << ") != number of cells (" << numCells << ")"
154 << exit(FatalError);
155 }
156
157 // Cell weights (so on the vertices of the dual)
158 List<int> cellWeights;
159
160 if (hasWeights)
161 {
162 // Convert to integers.
163 cellWeights.resize_nocopy(cWeights.size());
164 forAll(cellWeights, i)
165 {
166 cellWeights[i] = static_cast<int>
167 (
168 cWeights[i]/minWeights
169 );
170 }
171 }
172
173 configNames.readIfPresent("config", coeffsDict_, kahipConfig);
174 coeffsDict_.readIfPresent("imbalance", imbalance);
175 coeffsDict_.readIfPresent("verbose", verbose);
176
177 Info<< "kahipDecomp :"
178 << " config=" << configNames[kahipConfig]
179 << " imbalance=" << imbalance;
180
181 if (coeffsDict_.readIfPresent("seed", seed))
182 {
183 Info<< " seed=" << seed;
184 }
185
186 // Additional sizing parameters (testing only)
187 std::map<std::string, std::vector<int>> sizingParams;
188
189 List<int> labels;
190 if
191 (
192 coeffsDict_.readIfPresent("hierarchy", labels)
193 && !labels.empty()
194 )
195 {
196 std::vector<int> vec;
197 vec.reserve(labels.size()+1);
198
199 // Verify sizing
200
201 int n = 1;
202 for (const auto val : labels)
203 {
204 n *= val;
205 vec.push_back(val);
206 }
207
208 if (n != nDomains_)
209 {
210 // Size mismatch. Try to correct.
211
212 if (nDomains_ % n)
213 {
215 << "Mismatch in number of processors and "
216 << "hierarchy specified" << flatOutput(labels) << endl;
217
218 vec.clear();
219 }
220 else
221 {
222 // Evenly divisible, add extra hierarchy level
223 vec.push_back(nDomains_ / n);
224 }
225 }
226
227 if (!vec.empty())
228 {
229 sizingParams["hierarchy"] = std::move(vec);
230 Info<< " hierarchy=" << flatOutput(labels);
231 }
232 }
233
234 if
235 (
236 coeffsDict_.readIfPresent("distance", labels)
237 && !labels.empty()
238 )
239 {
240 std::vector<int> vec(labels.size());
241
242 forAll(labels, i)
243 {
244 vec[i] = labels[i];
245 }
246
247 sizingParams["distance"] = std::move(vec);
248 Info<< " distance=" << flatOutput(labels);
249 }
250
251 Info<< endl;
252
253
254 // Number of partitions
255 int nParts = nDomains_;
256
257 // Output: number of cut edges
258 int edgeCut = 0;
259
260
261#if 0 // WIP: #ifdef KAFFPA_CPP_INTERFACE
262 kaffpa_cpp
263 (
264 &numCells, // num vertices in graph
265 (cellWeights.empty() ? nullptr : cellWeights.data()), // vertex wts
266 xadj_param.constCast().data(), // indexing into adjncy
267 nullptr, // edge wts
268 adjncy_param.constCast().data(), // neighbour info
269 &nParts, // nparts
270 &imbalance, // amount of imbalance allowed
271 !verbose, // suppress output
272 seed, // for random
273 int(kahipConfig),
274 &edgeCut, // [output]
275 decomp_param.ref().data(), // [output]
276 sizingParams
277 );
278#else
279 kaffpa
280 (
281 &numCells, // num vertices in graph
282 (cellWeights.empty() ? nullptr : cellWeights.data()), // vertex wts
283 xadj_param.constCast().data(), // indexing into adjncy
284 nullptr, // edge wts
285 adjncy_param.constCast().data(), // neighbour info
286 &nParts, // nparts
287 &imbalance, // amount of imbalance allowed
288 !verbose, // suppress output
289 seed, // for random
290 int(kahipConfig),
291 &edgeCut, // [output]
292 decomp_param.ref().data() // [output]
293 );
294#endif
296 return edgeCut;
297}
298
299
300// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
302Foam::kahipDecomp::kahipDecomp(const label numDomains)
303:
304 metisLikeDecomp(numDomains)
305{}
306
307
309(
310 const dictionary& decompDict,
311 const word& regionName
312)
313:
314 metisLikeDecomp(typeName, decompDict, regionName, selectionType::NULL_DICT)
315{}
316
317
318// ************************************************************************* //
if(maxValue - minValue< SMALL)
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.
A const Field/List wrapper with possible data conversion.
void set(const Container< InputType > &input)
Set adaptor for different input, copying input if required.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition Enum.H:57
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
A non-const Field/List wrapper with possible data conversion.
void set(Container< InputType > &input, const bool doCopy=true)
Set adaptor for different input, copying input as required.
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition UListI.H:274
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
Abstract base class for domain decomposition.
selectionType
Selection type when handling the coefficients dictionary.
label nDomains_
Number of domains for the decomposition.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
Domain decomposition using KaHIP http://algo2.iti.kit.edu/documents/kahip/.
Definition kahipDecomp.H:93
kahipDecomp(const kahipDecomp &)=delete
No copy construct.
virtual label decomposeSerial(const labelList &adjncy, const labelList &xadj, const List< scalar > &cellWeights, labelList &decomp) const
Call kahip with options from dictionary.
Definition kahipDecomp.C:74
configs
The predefined KaHIP configuration types.
static const Enum< configs > configNames
The selection names for predefined KaHIP configurations.
Domain decomposition using METIS-like data structures.
const dictionary & coeffsDict_
Coefficients for all derived methods.
metisLikeDecomp(const metisLikeDecomp &)=delete
No copy construct.
T & constCast() const
Return non-const reference to the object or to the contents of a (non-null) managed pointer,...
Definition refPtr.H:278
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition refPtrI.H:303
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition refPtrI.H:230
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#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:40
List< label > labelList
A List of labels.
Definition List.H:62
messageStream Info
Information stream (stdout output on master, null elsewhere).
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299