Nektar++
MeshPartitionScotch.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File MeshPartitionScotch.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Scotch partitioner interface
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <boost/core/ignore_unused.hpp>
36 
38 
39 namespace Nektar
40 {
41 namespace SpatialDomains
42 {
43 
46  "Scotch",
48  "Partitioning using the Scotch library.");
49 
52  "use-scotch","","Use Scotch for mesh partitioning.");
53 
56  int meshDim,
57  std::map<int, MeshEntity> element,
58  CompositeDescriptor compMap)
59  : MeshPartition(session, meshDim, element, compMap)
60  {
61  }
62 
64  {
65 
66  }
67 
69  int& nVerts,
70  int& nVertConds,
76  int& nparts,
77  int& volume,
79  {
80  boost::ignore_unused(nVertConds, edgeWgt);
81 
82  int wgtflag = 0;
83  int *vwgt = 0;
84  int *vsize = 0;
85  if (vertWgt.num_elements() > 0)
86  {
87  wgtflag += 1;
88  vwgt = &vertWgt[0];
89  }
90  if (vertSize.num_elements() > 0)
91  {
92  wgtflag += 2;
93  vsize = &vertSize[0];
94  }
95  int numflag = 0;
96 
97  PartGraphVKway(&nVerts, &xadj[0], &adjcy[0], vwgt, vsize,
98  &wgtflag, &numflag, &nparts, &volume,
99  &part[0]);
100  }
101 
102 
104  const SCOTCH_Num * const n,
105  const SCOTCH_Num * const xadj,
106  const SCOTCH_Num * const adjncy,
107  const SCOTCH_Num * const vwgt,
108  const SCOTCH_Num * const vsize,
109  const SCOTCH_Num * const wgtflag,
110  const SCOTCH_Num * const numflag,
111  const SCOTCH_Num * const nparts,
112  SCOTCH_Num * const volume,
113  SCOTCH_Num * const part)
114  {
115  SCOTCH_Num baseval;
116  const SCOTCH_Num * vwgt2;
117  const SCOTCH_Num * vsize2;
118  SCOTCH_Num vsizval; /// Communication volume of current vertex
119  SCOTCH_Num vertnbr;
120  SCOTCH_Num vertnum;
121  SCOTCH_Num edgenum;
122  const SCOTCH_Num * edgetax;
123  const SCOTCH_Num * parttax;
124  SCOTCH_Num * nghbtab;
125  SCOTCH_Num commvol;
126 
127  vsize2 = ((*wgtflag & 1) != 0) ? vsize : NULL;
128  vwgt2 = ((*wgtflag & 2) != 0) ? vwgt : NULL;
129  baseval = *numflag;
130  vertnbr = *n;
131  edgetax = adjncy - baseval;
132 
133  // If no communication load data provided
134  if (vsize2 == NULL) {
135  if (PartGraph2 (n, xadj, adjncy, vwgt2, NULL, numflag, nparts,
136  part, SCOTCH_STRATQUALITY, 0.01) != 0)
137  return;
138  }
139 
140  // Will have to turn communication volumes into edge loads
141  else {
142  const SCOTCH_Num * vsiztax;
143  SCOTCH_Num edgenbr;
144  SCOTCH_Num * edlotax;
145  int o;
146 
147  edgenbr = xadj[vertnbr] - baseval;
148  if ((edlotax =
149  (SCOTCH_Num*) malloc (edgenbr * sizeof (SCOTCH_Num))) == NULL)
150  {
151  return;
152  }
153 
154  edlotax -= baseval; // Base access to edlotax
155  vsiztax = vsize2 - baseval;
156 
157  // Un-based scan of vertex array xadj
158  for (vertnum = 0, edgenum = baseval;
159  vertnum < vertnbr; vertnum ++) {
160  SCOTCH_Num vsizval; // Communication size of current vertex
161  SCOTCH_Num edgennd;
162 
163  vsizval = vsize2[vertnum];
164  // Based traversal of edge array adjncy
165  for (edgennd = xadj[vertnum + 1];
166  edgenum < edgennd;
167  edgenum ++) {
168 
169  SCOTCH_Num vertend; // Based end vertex number
170 
171  vertend = edgetax[edgenum];
172  edlotax[edgenum] = vsizval + vsiztax[vertend];
173  }
174  }
175 
176  o = PartGraph2 (n, xadj, adjncy, vwgt2, edlotax + baseval, numflag,
177  nparts, part, SCOTCH_STRATQUALITY, 0.01);
178 
179  free (edlotax + baseval);
180 
181  if (o != 0)
182  return;
183  }
184 
185  if ((nghbtab =
186  (SCOTCH_Num*) malloc (*nparts * sizeof (SCOTCH_Num))) == NULL)
187  {
188  return;
189  }
190 
191  memset (nghbtab, ~0, *nparts * sizeof (SCOTCH_Num));
192 
193  parttax = part - baseval;
194  vsizval = 1; // Assume no vertex communication sizes
195 
196  // Un-based scan of vertex array xadj
197  for (vertnum = 0, edgenum = baseval, commvol = 0;
198  vertnum < vertnbr; vertnum ++) {
199  SCOTCH_Num partval;
200  SCOTCH_Num edgennd;
201 
202  partval = part[vertnum];
203  nghbtab[partval] = vertnum; // Do not count local neighbors in
204  // communication volume
205  if (vsize2 != NULL)
206  vsizval = vsize2[vertnum];
207 
208  // Based traversal of edge array adjncy
209  for (edgennd = xadj[vertnum + 1]; edgenum < edgennd; edgenum ++) {
210  SCOTCH_Num vertend; // Based end vertex number
211  SCOTCH_Num partend;
212 
213  vertend = edgetax[edgenum];
214  partend = parttax[vertend];
215 
216  // If first neighbor in this part set part as accounted for
217  if (nghbtab[partend] != vertnum) {
218  nghbtab[partend] = vertnum;
219  commvol += vsizval;
220  }
221  }
222  }
223  *volume = commvol;
224 
225  free (nghbtab);
226  }
227 
229  const SCOTCH_Num * const n,
230  const SCOTCH_Num * const xadj,
231  const SCOTCH_Num * const adjncy,
232  const SCOTCH_Num * const vwgt,
233  const SCOTCH_Num * const adjwgt,
234  const SCOTCH_Num * const numflag,
235  const SCOTCH_Num * const nparts,
236  SCOTCH_Num * const part,
237  SCOTCH_Num flagval,
238  double kbalval)
239  {
240  // Scotch graph object to interface with libScotch
241  SCOTCH_Graph * grafdat = SCOTCH_graphAlloc();
242  SCOTCH_Strat stradat;
243  SCOTCH_Num baseval;
244  SCOTCH_Num vertnbr;
245  int o;
246 
247  SCOTCH_graphInit (grafdat);
248 
249  baseval = *numflag;
250  vertnbr = *n;
251 
252  o = 1; // Assume something will go wrong
253  if (SCOTCH_graphBuild (grafdat, baseval, vertnbr, xadj, xadj + 1,
254  vwgt, NULL, xadj[vertnbr] - baseval, adjncy,
255  adjwgt) == 0) {
256  SCOTCH_stratInit (&stradat);
257  SCOTCH_stratGraphMapBuild (&stradat, flagval, *nparts, kbalval);
258 #ifdef SCOTCH_DEBUG_ALL
259  // TRICK: next instruction called only if graph is consistent
260  if (SCOTCH_graphCheck (grafdat) == 0)
261 #endif /* SCOTCH_DEBUG_ALL */
262  o = SCOTCH_graphPart (grafdat, *nparts, &stradat, part);
263  SCOTCH_stratExit (&stradat);
264  }
265  SCOTCH_graphExit (grafdat);
266 
267  if (o != 0)
268  return (1);
269 
270  if (baseval != 0) { // MeTiS part array is based, Scotch is not
271  SCOTCH_Num vertnum;
272 
273  for (vertnum = 0; vertnum < vertnbr; vertnum ++)
274  part[vertnum] += baseval;
275  }
276 
277  return (0);
278  }
279 
280 }
281 }
static std::string RegisterCmdLineFlag(const std::string &pName, const std::string &pShortName, const std::string &pDescription)
Registers a command-line flag with the session reader.
virtual void PartitionGraphImpl(int &nVerts, int &nVertConds, Nektar::Array< Nektar::OneD, int > &xadj, Nektar::Array< Nektar::OneD, int > &adjcy, Nektar::Array< Nektar::OneD, int > &vertWgt, Nektar::Array< Nektar::OneD, int > &vertSize, Nektar::Array< Nektar::OneD, int > &edgeWgt, int &nparts, int &volume, Nektar::Array< Nektar::OneD, int > &part)
MeshPartitionScotch(const LibUtilities::SessionReaderSharedPtr session, int meshDim, std::map< int, MeshEntity > element, CompositeDescriptor compMap)
int PartGraph2(const SCOTCH_Num *const n, const SCOTCH_Num *const xadj, const SCOTCH_Num *const adjncy, const SCOTCH_Num *const vwgt, const SCOTCH_Num *const adjwgt, const SCOTCH_Num *const numflag, const SCOTCH_Num *const nparts, SCOTCH_Num *const part, SCOTCH_Num flagval, double kbalval)
static MeshPartitionSharedPtr create(const LibUtilities::SessionReaderSharedPtr session, int meshDim, std::map< int, MeshEntity > element, CompositeDescriptor compMap)
Creates an instance of this class.
std::map< int, std::pair< LibUtilities::ShapeType, std::vector< int > > > CompositeDescriptor
Definition: MeshGraph.h:62
void PartGraphVKway(const SCOTCH_Num *const n, const SCOTCH_Num *const xadj, const SCOTCH_Num *const adjncy, const SCOTCH_Num *const vwgt, const SCOTCH_Num *const vsize, const SCOTCH_Num *const wgtflag, const SCOTCH_Num *const numflag, const SCOTCH_Num *const nparts, SCOTCH_Num *const volume, SCOTCH_Num *const part)
static std::string className
Name of class.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
MeshPartitionFactory & GetMeshPartitionFactory()
std::shared_ptr< SessionReader > SessionReaderSharedPtr