1 /*!
2 \file cmdline_mpmetis.c
3 
4 \brief Command-line argument parsing for mpmetis
5 
6 \date 12/24/2008
7 \author George
8 \version\verbatim $Id: cmdline_mpmetis.c 13905 2013-03-25 13:21:20Z karypis $\endverbatim
9 */
10 
11 #include "metisbin.h"
12 
13 
14 /*-------------------------------------------------------------------
15  * Command-line options
16  *-------------------------------------------------------------------*/
17 static struct gk_option long_options[] = {
18   {"gtype",          1,      0,      METIS_OPTION_GTYPE},
19   {"ptype",          1,      0,      METIS_OPTION_PTYPE},
20   {"objtype",        1,      0,      METIS_OPTION_OBJTYPE},
21 
22   {"ctype",          1,      0,      METIS_OPTION_CTYPE},
23   {"iptype",         1,      0,      METIS_OPTION_IPTYPE},
24 
25   {"minconn",        0,      0,      METIS_OPTION_MINCONN},
26   {"contig",         0,      0,      METIS_OPTION_CONTIG},
27 
28   {"nooutput",       0,      0,      METIS_OPTION_NOOUTPUT},
29 
30   {"ufactor",        1,      0,      METIS_OPTION_UFACTOR},
31   {"niter",          1,      0,      METIS_OPTION_NITER},
32   {"ncuts",          1,      0,      METIS_OPTION_NCUTS},
33   {"ncommon",        1,      0,      METIS_OPTION_NCOMMON},
34 
35   {"tpwgts",         1,      0,      METIS_OPTION_TPWGTS},
36 
37   {"seed",           1,      0,      METIS_OPTION_SEED},
38 
39   {"dbglvl",         1,      0,      METIS_OPTION_DBGLVL},
40 
41   {"help",           0,      0,      METIS_OPTION_HELP},
42   {0,                0,      0,      0}
43 };
44 
45 
46 
47 /*-------------------------------------------------------------------
48  * Mappings for the various parameter values
49  *-------------------------------------------------------------------*/
50 static gk_StringMap_t gtype_options[] = {
51  {"dual",               METIS_GTYPE_DUAL},
52  {"nodal",              METIS_GTYPE_NODAL},
53  {NULL,                 0}
54 };
55 
56 static gk_StringMap_t ptype_options[] = {
57  {"rb",                 METIS_PTYPE_RB},
58  {"kway",               METIS_PTYPE_KWAY},
59  {NULL,                 0}
60 };
61 
62 static gk_StringMap_t objtype_options[] = {
63  {"cut",                METIS_OBJTYPE_CUT},
64  {"vol",                METIS_OBJTYPE_VOL},
65  {NULL,                 0}
66 };
67 
68 static gk_StringMap_t ctype_options[] = {
69  {"rm",                 METIS_CTYPE_RM},
70  {"shem",               METIS_CTYPE_SHEM},
71  {NULL,                 0}
72 };
73 
74 static gk_StringMap_t iptype_options[] = {
75  {"grow",               METIS_IPTYPE_GROW},
76  {"random",             METIS_IPTYPE_RANDOM},
77  {NULL,                 0}
78 };
79 
80 
81 /*-------------------------------------------------------------------
82  * Mini help
83  *-------------------------------------------------------------------*/
84 static char helpstr[][100] =
85 {
86 " ",
87 "Usage: mpmetis [options] meshfile nparts",
88 " ",
89 " Required parameters",
90 "    meshfile    Stores the mesh to be partitioned.",
91 "    nparts      The number of partitions to split the mesh.",
92 " ",
93 " Optional parameters",
94 "  -gtype=string",
95 "     Specifies the graph to be used for computing the partitioning",
96 "     The possible values are:",
97 "        dual     - Partition the dual graph of the mesh [default]",
98 "        nodal    - Partition the nodal graph of the mesh",
99 " ",
100 "  -ptype=string",
101 "     Specifies the scheme to be used for computing the k-way partitioning.",
102 "     The possible values are:",
103 "        rb       - Recursive bisectioning",
104 "        kway     - Direct k-way partitioning [default]",
105 " ",
106 "  -ctype=string",
107 "     Specifies the scheme to be used to match the vertices of the graph",
108 "     during the coarsening.",
109 "     The possible values are:",
110 "        rm       - Random matching",
111 "        shem     - Sorted heavy-edge matching [default]",
112 " ",
113 "  -iptype=string [applies only when -ptype=rb]",
114 "     Specifies the scheme to be used to compute the initial partitioning",
115 "     of the graph.",
116 "     The possible values are:",
117 "        grow     - Grow a bisection using a greedy strategy [default]",
118 "        random   - Compute a bisection at random",
119 " ",
120 "  -objtype=string [applies only when -ptype=kway]",
121 "     Specifies the objective that the partitioning routines will optimize.",
122 "     The possible values are:",
123 "        cut      - Minimize the edgecut [default]",
124 "        vol      - Minimize the total communication volume",
125 " ",
126 "  -contig [applies only when -ptype=kway]",
127 "     Specifies that the partitioning routines should try to produce",
128 "     partitions that are contiguous. Note that if the input graph is not",
129 "     connected this option is ignored.",
130 " ",
131 "  -minconn [applies only when -ptype=kway]",
132 "     Specifies that the partitioning routines should try to minimize the",
133 "     maximum degree of the subdomain graph, i.e., the graph in which each",
134 "     partition is a node, and edges connect subdomains with a shared",
135 "     interface.",
136 " ",
137 "  -tpwgts=filename",
138 "     Specifies the name of the file that stores the target weights for",
139 "     each partition. By default, all partitions are assumed to be of ",
140 "     the same size.",
141 " ",
142 "  -ufactor=int",
143 "     Specifies the maximum allowed load imbalance among the partitions.",
144 "     A value of x indicates that the allowed load imbalance is 1+x/1000.",
145 "     For ptype=rb, the load imbalance is measured as the ratio of the ",
146 "     2*max(left,right)/(left+right), where left and right are the sizes",
147 "     of the respective partitions at each bisection. ",
148 "     For ptype=kway, the load imbalance is measured as the ratio of ",
149 "     max_i(pwgts[i])/avgpwgt, where pwgts[i] is the weight of the ith",
150 "     partition and avgpwgt is the sum of the total vertex weights divided",
151 "     by the number of partitions requested.",
152 "     For ptype=rb, the default value is 1 (i.e., load imbalance of 1.001).",
153 "     For ptype=kway, the default value is 30 (i.e., load imbalance of 1.03).",
154 " ",
155 "  -ncommon=int",
156 "     Specifies the common number of nodes that two elements must have",
157 "     in order to put an edge between them in the dual graph. Default is 1.",
158 " ",
159 "  -niter=int",
160 "     Specifies the number of iterations for the refinement algorithms",
161 "     at each stage of the uncoarsening process. Default is 10.",
162 " ",
163 "  -ncuts=int",
164 "     Specifies the number of different partitionings that it will compute.",
165 "     The final partitioning is the one that achieves the best edgecut or",
166 "     communication volume. Default is 1.",
167 " ",
168 "  -nooutput",
169 "     Specifies that no partitioning file should be generated.",
170 " ",
171 "  -seed=int",
172 "     Selects the seed of the random number generator.  ",
173 " ",
174 "  -dbglvl=int      ",
175 "     Selects the dbglvl.  ",
176 " ",
177 "  -help",
178 "     Prints this message.",
179 ""
180 };
181 
182 static char shorthelpstr[][100] = {
183 " ",
184 "   Usage: mpmetis [options] <filename> <nparts>",
185 "          use 'mpmetis -help' for a summary of the options.",
186 ""
187 };
188 
189 
190 
191 /*************************************************************************
192 * This is the entry point of the command-line argument parser
193 **************************************************************************/
parse_cmdline(int argc,char * argv[])194 params_t *parse_cmdline(int argc, char *argv[])
195 {
196   int i, j, k;
197   int c, option_index;
198   params_t *params;
199 
200   params = (params_t *)gk_malloc(sizeof(params_t), "parse_cmdline");
201   memset((void *)params, 0, sizeof(params_t));
202 
203   /* initialize the params data structure */
204   params->gtype         = METIS_GTYPE_DUAL;
205   params->ptype         = METIS_PTYPE_KWAY;
206   params->objtype       = METIS_OBJTYPE_CUT;
207   params->ctype         = METIS_CTYPE_SHEM;
208   params->iptype        = METIS_IPTYPE_GROW;
209   params->rtype         = -1;
210 
211   params->minconn       = 0;
212   params->contig        = 0;
213 
214   params->nooutput      = 0;
215   params->wgtflag       = 3;
216 
217   params->ncuts         = 1;
218   params->niter         = 10;
219   params->ncommon       = 1;
220 
221   params->dbglvl        = 0;
222   params->balance       = 0;
223   params->seed          = -1;
224   params->dbglvl        = 0;
225 
226   params->tpwgtsfile    = NULL;
227 
228   params->filename      = NULL;
229   params->nparts        = 1;
230 
231   params->ufactor       = -1;
232 
233   gk_clearcputimer(params->iotimer);
234   gk_clearcputimer(params->parttimer);
235   gk_clearcputimer(params->reporttimer);
236 
237 
238   /* Parse the command line arguments  */
239   while ((c = gk_getopt_long_only(argc, argv, "", long_options, &option_index)) != -1) {
240     switch (c) {
241       case METIS_OPTION_GTYPE:
242         if (gk_optarg)
243           if ((params->gtype = gk_GetStringID(gtype_options, gk_optarg)) == -1)
244             errexit("Invalid option -%s=%s\n", long_options[option_index].name, gk_optarg);
245         break;
246       case METIS_OPTION_PTYPE:
247         if (gk_optarg)
248           if ((params->ptype = gk_GetStringID(ptype_options, gk_optarg)) == -1)
249             errexit("Invalid option -%s=%s\n", long_options[option_index].name, gk_optarg);
250         break;
251       case METIS_OPTION_OBJTYPE:
252         if (gk_optarg)
253           if ((params->objtype = gk_GetStringID(objtype_options, gk_optarg)) == -1)
254             errexit("Invalid option -%s=%s\n", long_options[option_index].name, gk_optarg);
255         break;
256       case METIS_OPTION_CTYPE:
257         if (gk_optarg)
258           if ((params->ctype = gk_GetStringID(ctype_options, gk_optarg)) == -1)
259             errexit("Invalid option -%s=%s\n", long_options[option_index].name, gk_optarg);
260         break;
261       case METIS_OPTION_IPTYPE:
262         if (gk_optarg)
263           if ((params->iptype = gk_GetStringID(iptype_options, gk_optarg)) == -1)
264             errexit("Invalid option -%s=%s\n", long_options[option_index].name, gk_optarg);
265         break;
266 
267 /*
268       case METIS_OPTION_RTYPE:
269         if (gk_optarg)
270           if ((params->rtype = gk_GetStringID(rtype_options, gk_optarg)) == -1)
271             errexit("Invalid option -%s=%s\n", long_options[option_index].name, gk_optarg);
272         break;
273 */
274 
275       case METIS_OPTION_CONTIG:
276         params->contig = 1;
277         break;
278 
279       case METIS_OPTION_MINCONN:
280         params->minconn = 1;
281         break;
282 
283       case METIS_OPTION_NOOUTPUT:
284         params->nooutput = 1;
285         break;
286 
287       case METIS_OPTION_BALANCE:
288         params->balance = 1;
289         break;
290 
291       case METIS_OPTION_TPWGTS:
292         if (gk_optarg) params->tpwgtsfile = gk_strdup(gk_optarg);
293         break;
294 
295       case METIS_OPTION_NCUTS:
296         if (gk_optarg) params->ncuts = (idx_t)atoi(gk_optarg);
297         break;
298       case METIS_OPTION_NITER:
299         if (gk_optarg) params->niter = (idx_t)atoi(gk_optarg);
300         break;
301 
302       case METIS_OPTION_NCOMMON:
303         if (gk_optarg) params->ncommon = (idx_t)atoi(gk_optarg);
304         break;
305 
306       case METIS_OPTION_UFACTOR:
307         if (gk_optarg) params->ufactor = (idx_t)atoi(gk_optarg);
308         break;
309 
310       case METIS_OPTION_SEED:
311         if (gk_optarg) params->seed = (idx_t)atoi(gk_optarg);
312         break;
313 
314       case METIS_OPTION_DBGLVL:
315         if (gk_optarg) params->dbglvl = (idx_t)atoi(gk_optarg);
316         break;
317 
318       case METIS_OPTION_HELP:
319         for (i=0; strlen(helpstr[i]) > 0; i++)
320           printf("%s\n", helpstr[i]);
321         exit(0);
322         break;
323       case '?':
324       default:
325         errexit("Illegal command-line option(s)\n"
326                 "Use %s -help for a summary of the options.\n", argv[0]);
327     }
328   }
329 
330   if (argc-gk_optind != 2) {
331     printf("Missing parameters.");
332     for (i=0; strlen(shorthelpstr[i]) > 0; i++)
333       printf("%s\n", shorthelpstr[i]);
334     exit(0);
335   }
336 
337   params->filename = gk_strdup(argv[gk_optind++]);
338   params->nparts   = atoi(argv[gk_optind++]);
339 
340   if (params->nparts < 2)
341     errexit("The number of partitions should be greater than 1!\n");
342 
343 
344   /* Set the ptype-specific defaults */
345   if (params->ptype == METIS_PTYPE_RB) {
346     params->rtype = METIS_RTYPE_FM;
347   }
348   if (params->ptype == METIS_PTYPE_KWAY) {
349     params->iptype = METIS_IPTYPE_METISRB;
350     params->rtype  = METIS_RTYPE_GREEDY;
351   }
352 
353   /* Check for invalid parameter combination */
354   if (params->ptype == METIS_PTYPE_RB) {
355     if (params->contig)
356       errexit("The -contig option cannot be specified with rb partitioning.\n");
357     if (params->minconn)
358       errexit("The -minconn option cannot be specified with rb partitioning.\n");
359     if (params->objtype == METIS_OBJTYPE_VOL)
360       errexit("The -objtype=vol option cannot be specified with rb partitioning.\n");
361   }
362 
363   return params;
364 }
365 
366 
367