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