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 
57  int meshDim,
58  std::map<int, MeshEntity> element,
59  CompositeDescriptor compMap)
60  : MeshPartition(session, comm, meshDim, element, compMap)
61  {
62  }
63 
65  {
66 
67  }
68 
70  int& nVerts,
71  int& nVertConds,
77  int& nparts,
78  int& volume,
80  {
81  boost::ignore_unused(nVertConds, edgeWgt);
82 
83  int wgtflag = 0;
84  int *vwgt = 0;
85  int *vsize = 0;
86  if (vertWgt.size() > 0)
87  {
88  wgtflag += 1;
89  vwgt = &vertWgt[0];
90  }
91  if (vertSize.size() > 0)
92  {
93  wgtflag += 2;
94  vsize = &vertSize[0];
95  }
96  int numflag = 0;
97 
98  PartGraphVKway(&nVerts, &xadj[0], &adjcy[0], vwgt, vsize,
99  &wgtflag, &numflag, &nparts, &volume,
100  &part[0]);
101  }
102 
103 
105  const SCOTCH_Num * const n,
106  const SCOTCH_Num * const xadj,
107  const SCOTCH_Num * const adjncy,
108  const SCOTCH_Num * const vwgt,
109  const SCOTCH_Num * const vsize,
110  const SCOTCH_Num * const wgtflag,
111  const SCOTCH_Num * const numflag,
112  const SCOTCH_Num * const nparts,
113  SCOTCH_Num * const volume,
114  SCOTCH_Num * const part)
115  {
116  SCOTCH_Num baseval;
117  const SCOTCH_Num * vwgt2;
118  const SCOTCH_Num * vsize2;
119  SCOTCH_Num vsizval; /// Communication volume of current vertex
120  SCOTCH_Num vertnbr;
121  SCOTCH_Num vertnum;
122  SCOTCH_Num edgenum;
123  const SCOTCH_Num * edgetax;
124  const SCOTCH_Num * parttax;
125  SCOTCH_Num * nghbtab;
126  SCOTCH_Num commvol;
127 
128  vsize2 = ((*wgtflag & 1) != 0) ? vsize : NULL;
129  vwgt2 = ((*wgtflag & 2) != 0) ? vwgt : NULL;
130  baseval = *numflag;
131  vertnbr = *n;
132  edgetax = adjncy - baseval;
133 
134  // If no communication load data provided
135  if (vsize2 == NULL) {
136  if (PartGraph2 (n, xadj, adjncy, vwgt2, NULL, numflag, nparts,
137  part, SCOTCH_STRATQUALITY, 0.01) != 0)
138  return;
139  }
140 
141  // Will have to turn communication volumes into edge loads
142  else {
143  const SCOTCH_Num * vsiztax;
144  SCOTCH_Num edgenbr;
145  SCOTCH_Num * edlotax;
146  int o;
147 
148  edgenbr = xadj[vertnbr] - baseval;
149  if ((edlotax =
150  (SCOTCH_Num*) malloc (edgenbr * sizeof (SCOTCH_Num))) == NULL)
151  {
152  return;
153  }
154 
155  edlotax -= baseval; // Base access to edlotax
156  vsiztax = vsize2 - baseval;
157 
158  // Un-based scan of vertex array xadj
159  for (vertnum = 0, edgenum = baseval;
160  vertnum < vertnbr; vertnum ++) {
161  SCOTCH_Num vsizval; // Communication size of current vertex
162  SCOTCH_Num edgennd;
163 
164  vsizval = vsize2[vertnum];
165  // Based traversal of edge array adjncy
166  for (edgennd = xadj[vertnum + 1];
167  edgenum < edgennd;
168  edgenum ++) {
169 
170  SCOTCH_Num vertend; // Based end vertex number
171 
172  vertend = edgetax[edgenum];
173  edlotax[edgenum] = vsizval + vsiztax[vertend];
174  }
175  }
176 
177  o = PartGraph2 (n, xadj, adjncy, vwgt2, edlotax + baseval, numflag,
178  nparts, part, SCOTCH_STRATQUALITY, 0.01);
179 
180  free (edlotax + baseval);
181 
182  if (o != 0)
183  return;
184  }
185 
186  if ((nghbtab =
187  (SCOTCH_Num*) malloc (*nparts * sizeof (SCOTCH_Num))) == NULL)
188  {
189  return;
190  }
191 
192  memset (nghbtab, ~0, *nparts * sizeof (SCOTCH_Num));
193 
194  parttax = part - baseval;
195  vsizval = 1; // Assume no vertex communication sizes
196 
197  // Un-based scan of vertex array xadj
198  for (vertnum = 0, edgenum = baseval, commvol = 0;
199  vertnum < vertnbr; vertnum ++) {
200  SCOTCH_Num partval;
201  SCOTCH_Num edgennd;
202 
203  partval = part[vertnum];
204  nghbtab[partval] = vertnum; // Do not count local neighbors in
205  // communication volume
206  if (vsize2 != NULL)
207  vsizval = vsize2[vertnum];
208 
209  // Based traversal of edge array adjncy
210  for (edgennd = xadj[vertnum + 1]; edgenum < edgennd; edgenum ++) {
211  SCOTCH_Num vertend; // Based end vertex number
212  SCOTCH_Num partend;
213 
214  vertend = edgetax[edgenum];
215  partend = parttax[vertend];
216 
217  // If first neighbor in this part set part as accounted for
218  if (nghbtab[partend] != vertnum) {
219  nghbtab[partend] = vertnum;
220  commvol += vsizval;
221  }
222  }
223  }
224  *volume = commvol;
225 
226  free (nghbtab);
227  }
228 
230  const SCOTCH_Num * const n,
231  const SCOTCH_Num * const xadj,
232  const SCOTCH_Num * const adjncy,
233  const SCOTCH_Num * const vwgt,
234  const SCOTCH_Num * const adjwgt,
235  const SCOTCH_Num * const numflag,
236  const SCOTCH_Num * const nparts,
237  SCOTCH_Num * const part,
238  SCOTCH_Num flagval,
239  double kbalval)
240  {
241  // Scotch graph object to interface with libScotch
242  SCOTCH_Graph * grafdat = SCOTCH_graphAlloc();
243  SCOTCH_Strat stradat;
244  SCOTCH_Num baseval;
245  SCOTCH_Num vertnbr;
246  int o;
247 
248  SCOTCH_graphInit (grafdat);
249 
250  baseval = *numflag;
251  vertnbr = *n;
252 
253  o = 1; // Assume something will go wrong
254  if (SCOTCH_graphBuild (grafdat, baseval, vertnbr, xadj, xadj + 1,
255  vwgt, NULL, xadj[vertnbr] - baseval, adjncy,
256  adjwgt) == 0) {
257  SCOTCH_stratInit (&stradat);
258  SCOTCH_stratGraphMapBuild (&stradat, flagval, *nparts, kbalval);
259 #ifdef SCOTCH_DEBUG_ALL
260  // TRICK: next instruction called only if graph is consistent
261  if (SCOTCH_graphCheck (grafdat) == 0)
262 #endif /* SCOTCH_DEBUG_ALL */
263  o = SCOTCH_graphPart (grafdat, *nparts, &stradat, part);
264  SCOTCH_stratExit (&stradat);
265  }
266  SCOTCH_graphExit (grafdat);
267 
268  if (o != 0)
269  return (1);
270 
271  if (baseval != 0) { // MeTiS part array is based, Scotch is not
272  SCOTCH_Num vertnum;
273 
274  for (vertnum = 0; vertnum < vertnbr; vertnum ++)
275  part[vertnum] += baseval;
276  }
277 
278  return (0);
279  }
280 
281 }
282 }
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
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.
static MeshPartitionSharedPtr create(const LibUtilities::SessionReaderSharedPtr session, LibUtilities::CommSharedPtr comm, int meshDim, std::map< int, MeshEntity > element, CompositeDescriptor compMap)
Creates an instance of this class.
static std::string className
Name of class.
MeshPartitionScotch(const LibUtilities::SessionReaderSharedPtr session, LibUtilities::CommSharedPtr comm, int meshDim, std::map< int, MeshEntity > element, CompositeDescriptor compMap)
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)
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)
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)
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54
std::map< int, std::pair< LibUtilities::ShapeType, std::vector< int > > > CompositeDescriptor
Definition: MeshGraph.h:63
MeshPartitionFactory & GetMeshPartitionFactory()
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1