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 -------------------------------------------------------------------------------
10 License
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 
44 namespace Foam
45 {
46  defineTypeNameAndDebug(kahipDecomp, 0);
48  (
49  decompositionMethod,
50  kahipDecomp,
51  dictionary
52  );
53 }
54 
55 
56 const 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 // ************************************************************************* //
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::decompositionMethod::nDomains_
label nDomains_
Number of domains for the decomposition.
Definition: decompositionMethod.H:95
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
Foam::List::resize
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::metisLikeDecomp::coeffsDict_
const dictionary & coeffsDict_
Coefficients for all derived methods.
Definition: metisLikeDecomp.H:60
PrecisionAdaptor.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::kahipDecomp::decomposeSerial
virtual label decomposeSerial(const labelList &adjncy, const labelList &xadj, const List< scalar > &cellWeights, labelList &decomp) const
Call kahip with options from dictionary.
Definition: dummyKahipDecomp.C:57
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
n
label n
Definition: TABSMDCalcMethod2.H:31
regionName
Foam::word regionName
Definition: createNamedDynamicFvMesh.H:1
Foam::kahipDecomp::configNames
static const Enum< configs > configNames
The selection names for predefined KaHIP configurations.
Definition: kahipDecomp.H:134
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::kahipDecomp::configs
configs
The predefined KaHIP configuration types.
Definition: kahipDecomp.H:122
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:216
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Time.H
Foam::kahipDecomp::configs::FAST
default
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::Enum::readIfPresent
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
Foam::kahipDecomp::kahipDecomp
kahipDecomp(const kahipDecomp &)=delete
No copy construct.
kahipDecomp.H
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:405