Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Scotch partitioner interface
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
38 
39 #include "MeshPartitionScotch.h"
40 
41 namespace Nektar
42 {
43 namespace LibUtilities
44 {
45 
48  "Scotch",
50  "Partitioning using the Scotch library.");
51 
53  = SessionReader::RegisterCmdLineFlag("use-scotch","","Use Scotch for mesh partitioning.");
54 
56  : MeshPartition(pSession)
57  {
58 
59  }
60 
62  {
63 
64  }
65 
67  int& nVerts,
68  int& nVertConds,
74  int& nparts,
75  int& volume,
77  {
78  int wgtflag = 0;
79  int *vwgt = 0;
80  int *vsize = 0;
81  if (vertWgt.num_elements() > 0)
82  {
83  wgtflag += 1;
84  vwgt = &vertWgt[0];
85  }
86  if (vertSize.num_elements() > 0)
87  {
88  wgtflag += 2;
89  vsize = &vertSize[0];
90  }
91  int numflag = 0;
92  // number of balancing conditions (size of vertex multi-weight)
93  int options[5];
94  options[0] = 0;
95 
96  PartGraphVKway(&nVerts, &xadj[0], &adjcy[0], vwgt, vsize,
97  &wgtflag, &numflag, &nparts, options, &volume,
98  &part[0]);
99  }
100 
101 
103  const SCOTCH_Num * const n,
104  const SCOTCH_Num * const xadj,
105  const SCOTCH_Num * const adjncy,
106  const SCOTCH_Num * const vwgt,
107  const SCOTCH_Num * const vsize,
108  const SCOTCH_Num * const wgtflag,
109  const SCOTCH_Num * const numflag,
110  const SCOTCH_Num * const nparts,
111  const SCOTCH_Num * const options,
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_STRATDEFAULT, 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_STRATDEFAULT, 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;
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)
static MeshPartitionSharedPtr create(const SessionReaderSharedPtr &pSession)
Creates an instance of this class.
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
MeshPartitionScotch(const SessionReaderSharedPtr &pSession)
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 std::string className
Name of class.
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, const SCOTCH_Num *const options, SCOTCH_Num *const volume, SCOTCH_Num *const part)
MeshPartitionFactory & GetMeshPartitionFactory()
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:215