OpenRadioss 2025.1.11
OpenRadioss project
Loading...
Searching...
No Matches
ddcreate.c
Go to the documentation of this file.
1/*****************************************************************************
2/
3/ SPACE (SPArse Cholesky Elimination) Library: ddcreate.c
4/
5/ author J"urgen Schulze, University of Paderborn
6/ created 00nov28
7/
8/ This file contains functions dealing with construction/coarsening
9/ of a domain decomposition
10/
11******************************************************************************
12
13Data type: struct domdec
14 graph_t *G; pointer to graph object
15 int ndom; number of domains
16 int domwght; total weight of domains
17 int *vtype; type of node (see comment below)
18 int *color; color of node (GRAY, BLACK, or WHITE)
19 int cwght[3]; weights of GRAY, BLACK, WHITE partitions
20 int *map; maps nodes to next coarser domain decomp.
21 struct domdec *prev; pointer to previous finer domain decomp.
22 struct domdec *next; pointer to next coarser domain decomp.
23Comments:
24 o Structure holds the domain decompositions constructed by the
25 coarsening process; it also holds the colorings of the domain decomp.
26 computed by the refinement process
27 o vtype[v]: represents the status of a node in the domain decomposition
28 0, iff status of v is unknown
29 1, iff v is a domain vertex
30 2, iff v is a multisector vertex
31 3, iff multisec v is eliminated and now forms a domain
32 4, iff multisec v is absorbed by another multisec/domain
33Methods in lib/ddcreate.c:
34- dd = newDomainDecomposition(int nvtx, int nedges);
35 o Initial: ndom = domwght = 0,
36 cwght[GRAY] = cwght[BLACK] = cwght[WHITE] = 0,
37 and prev = next = NULL
38- void freeDomainDecomposition(domdec_t *dd);
39- void printDomainDecomposition(domdec_t *dd);
40- void checkDomainDecomposition(domdec_t *dd);
41- void buildInitialDomains(graph_t *G, int *vtxlist, int *vtype, int *rep);
42 o determines initial domains according to the order of nodes in vtxlist;
43 furthermore, it sets rep[u] = v for all multisecs u that are adjacent
44 to only one domain v
45 o on start vtype[u] = 0 for all 0 <= u < nvtx, on return
46 vtype[u] = 1, iff u belongs to a domain (rep[u]=u => u is seed of domain)
47 vtype[u] = 2, iff u belongs to a multisec (rep[u]=u => u is seed)
48- void mergeMultisecs(graph_t *G, int *vtype, int *rep);
49 o merges all adjacent multisecs that do not share a common domain
50 o on return vtype[w] = 4, iff multisec w belongs to multisec cluster
51 u = rep[w]
52- dd = initialDomainDecomposition(graph_t *G, int *map, int *vtype, int *rep);
53 o allocates memory for the initial domain decomposition of G by calling
54 newDomainDecomposition and creates the domain decomposition according
55 to the vectors vtype and rep; the map vector maps vertices of G onto
56 vertices of dd
57- dd = constructDomainDecomposition(graph_t *G, int *map);
58 o constructs an initial domain decomposition for the graph G by calling
59 the functions (a) buildInitialDomains
60 (b) mergeMultisecs
61 (c) initialDomainDecomposition
62 vextor map identifies vertices of G in the domain decomposition
63- void computePriorities(domdec_t *dd, int *msvtxlist, int *key, int scoretype);
64 o computes for each multisec u in msvtxlist its priority key[u] according
65 to the node selection strategy scoretype
66- void eliminateMultisecs(domdec_t *dd, int *msvtxlist, int *rep);
67 o eliminates multisecs according to their order in msvtxlist; furthermore,
68 it sets rep[u] = v for all multisecs u that are adjacent to only one
69 newly formed domain v
70 o on return
71 dd->vtype[u] = 1, iff u is a domain (rep[u] = u)
72 dd->vtype[u] = 2, iff u is an uneliminated multisec (rep[u] = u)
73 dd->vtype[u] = 3, iff u is an eliminated multisec (rep[u] = u)
74 dd->vtype[u] = 4, iff multisec u is absorbed by new domain v = rep[u];
75- void findIndMultisecs(domdec_t *dd, int *msvtxlist, int *rep);
76 o searches all unelim./unabsorbed multisecs in msnvtxlist for
77 indistinguishable multisecs; sets dd->vtype[u] = 4 and rep[u] = v, iff
78 u, v are indistinguishable and v is the representative of u
79- dd2 = coarserDomainDecomposition(domdec_t* dd1, int *rep);
80 o allocates memory for the coarser domain decomposition by calling
81 newDomainDecomposition and creates the domain decomposition according
82 to the vectors dd1->vtype and rep; vector dd1->map identifies the
83 vertices of dd1 in dd2
84- void shrinkDomainDecomposition(domdec_t *dd, int scoretype);
85 o shrinks dd according to a chosen node selection strategy by calling
86 the functions (a) computePriorities
87 (b) eliminateMultisecs
88 (c) findIndMultisecs
89 (d) coarserDomainDecomposition
90 the coarser domain decomposition is appended to dd via prev/next pointers
91
92******************************************************************************/
93
94#include <space.h>
95
96
97/*****************************************************************************
98******************************************************************************/
101{ domdec_t *dd;
102
103 mymalloc(dd, 1, domdec_t);
104 mymalloc(dd->vtype, nvtx, PORD_INT);
105 mymalloc(dd->color, nvtx, PORD_INT);
106 mymalloc(dd->map, nvtx, PORD_INT);
107
108 dd->G = newGraph(nvtx, nedges);
109 dd->ndom = dd->domwght = 0;
110 dd->cwght[GRAY] = dd->cwght[BLACK] = dd->cwght[WHITE] = 0;
111 dd->prev = dd->next = NULL;
112
113 return(dd);
114}
115
116
117/*****************************************************************************
118******************************************************************************/
119void
121{
122 freeGraph(dd->G);
123 free(dd->vtype);
124 free(dd->color);
125 free(dd->map);
126 free(dd);
127}
128
129
130/*****************************************************************************
131******************************************************************************/
132void
134{ graph_t *G;
135 PORD_INT count, u, v, i, istart, istop;
136
137 G = dd->G;
138 printf("\n#nodes %d (#domains %d, weight %d), #edges %d, totvwght %d\n",
139 G->nvtx, dd->ndom, dd->domwght, G->nedges >> 1, G->totvwght);
140 printf("partition weights: S %d, B %d, W %d\n", dd->cwght[GRAY],
141 dd->cwght[BLACK], dd->cwght[WHITE]);
142 for (u = 0; u < G->nvtx; u++)
143 { count = 0;
144 printf("--- adjacency list of node %d (vtype %d, color %d, map %d\n",
145 u, dd->vtype[u], dd->color[u], dd->map[u]);
146 istart = G->xadj[u];
147 istop = G->xadj[u+1];
148 for (i = istart; i < istop; i++)
149 { v = G->adjncy[i];
150 printf("%5d (vtype %2d, color %2d)", v, dd->vtype[v], dd->color[v]);
151 if ((++count % 3) == 0)
152 printf("\n");
153 }
154 if ((count % 3) != 0)
155 printf("\n");
156 }
157}
158
159
160/*****************************************************************************
161******************************************************************************/
162void
164{ PORD_INT *xadj, *adjncy, *vwght, *vtype;
165 PORD_INT err, nvtx, ndom, domwght, dom, multi, u, v, i, istart, istop;
166
167 nvtx = dd->G->nvtx;
168 xadj = dd->G->xadj;
169 adjncy = dd->G->adjncy;
170 vwght = dd->G->vwght;
171 vtype = dd->vtype;
172
173 err = FALSE;
174 printf("checking domain decomposition (#nodes %d, #edges %d)\n",
175 dd->G->nvtx, dd->G->nedges >> 1);
176
177 ndom = domwght = 0;
178 for (u = 0; u < nvtx; u++)
179 { /* check node type */
180 if ((vtype[u] != 1) && (vtype[u] != 2))
181 { printf("ERROR: node %d is neither DOMAIN nor MULTISEC\n", u);
182 err = TRUE;
183 }
184 /* count domains and sum up their weight */
185 if (vtype[u] == 1)
186 { ndom++;
187 domwght += vwght[u];
188 }
189 /* check number of neighboring domains and multisecs */
190 dom = multi = 0;
191 istart = xadj[u];
192 istop = xadj[u+1];
193 for (i = istart; i < istop; i++)
194 { v = adjncy[i];
195 if (vtype[v] == 1) dom++;
196 if (vtype[v] == 2) multi++;
197 }
198 if ((vtype[u] == 1) && (dom > 0))
199 { printf("ERROR: domain %d is adjacent to other domain\n", u);
200 err = TRUE;
201 }
202 if ((vtype[u] == 2) && (dom < 2))
203 { printf("ERROR: less than 2 domains adjacent to multisec node %d\n", u);
204 err = TRUE;
205 }
206 if ((vtype[u] == 2) && (multi > 0))
207 { printf("ERROR: multisec %d is adjacent to other multisec nodes\n", u);
208 err = TRUE;
209 }
210 }
211 /* check number and weight of domains */
212 if ((ndom != dd->ndom) || (domwght != dd->domwght))
213 { printf("ERROR: number/size (%d/%d) of domains does not match with those in"
214 " domain decomp. (%d/%d)\n", ndom, domwght, dd->ndom, dd->domwght);
215 err = TRUE;
216 }
217 if (err) quit();
218}
219
220
221/*****************************************************************************
222******************************************************************************/
223void
225{ PORD_INT *xadj, *adjncy;
226 PORD_INT nvtx, u, v, w, i, j, jstart, jstop;
227
228 xadj = G->xadj;
229 adjncy = G->adjncy;
230 nvtx = G->nvtx;
231
232 /* --------------------------------------------------------------------
233 determine initial domains according to the order of nodes in vtxlist
234 -------------------------------------------------------------------- */
235 for (i = 0; i < nvtx; i++)
236 { u = vtxlist[i];
237 if (vtype[u] == 0)
238 { vtype[u] = 1;
239 jstart = xadj[u];
240 jstop = xadj[u+1];
241 for (j = jstart; j < jstop; j++)
242 { v = adjncy[j];
243 vtype[v] = 2;
244 }
245 }
246 }
247
248 /* ------------------------------------------------------------
249 eliminate all multisecs that are adjacent to only one domain
250 ------------------------------------------------------------ */
251 for (i = 0; i < nvtx; i++)
252 { u = vtxlist[i];
253 if (vtype[u] == 2)
254 { v = -1;
255 jstart = xadj[u];
256 jstop = xadj[u+1];
257 for (j = jstart; j < jstop; j++)
258 { w = adjncy[j];
259 if (vtype[w] == 1)
260 { if (v == -1)
261 v = rep[w]; /* u adjacent to domain v = rep[w] */
262 else if (v != rep[w])
263 { v = -1; /* u adjacent to another domain */
264 break;
265 }
266 }
267 }
268 if (v != -1) /* u absorbed by domain v */
269 { vtype[u] = 1;
270 rep[u] = v;
271 }
272 }
273 }
274}
275
276
277/*****************************************************************************
278******************************************************************************/
279void
281{ PORD_INT *xadj, *adjncy, *tmp, *queue;
282 PORD_INT nvtx, qhead, qtail, flag, keepon, u, v, w, x;
283 PORD_INT i, istart, istop, j, jstart, jstop;
284
285 nvtx = G->nvtx;
286 xadj = G->xadj;
287 adjncy = G->adjncy;
288
289 /* ------------------------
290 allocate working storage
291 ------------------------ */
292 mymalloc(tmp, nvtx, PORD_INT);
293 mymalloc(queue, nvtx, PORD_INT);
294 for (u = 0; u < nvtx; u++)
295 tmp[u] = -1;
296
297 /* -------------------------------------------------------
298 merge all adjacent multisecs that do not share a domain
299 ------------------------------------------------------- */
300 flag = 1;
301 for (u = 0; u < nvtx; u++)
302 if (vtype[u] == 2)
303 { qhead = 0; qtail = 1;
304 queue[0] = u;
305 vtype[u] = -2;
306
307 /* multisec u is the seed of a new cluster, mark all adj. domains */
308 istart = xadj[u];
309 istop = xadj[u+1];
310 for (i = istart; i < istop; i++)
311 { v = adjncy[i];
312 if (vtype[v] == 1)
313 tmp[rep[v]] = flag;
314 }
315
316 /* and now build the cluster */
317 while (qhead != qtail)
318 { v = queue[qhead++];
319 istart = xadj[v];
320 istop = xadj[v+1];
321 for (i = istart; i < istop; i++)
322 { keepon = TRUE;
323 w = adjncy[i];
324 if (vtype[w] == 2)
325 { jstart = xadj[w];
326 jstop = xadj[w+1];
327 for (j = jstart; j < jstop; j++)
328 { x = adjncy[j];
329 if ((vtype[x] == 1) && (tmp[rep[x]] == flag))
330 { keepon = FALSE;
331 break;
332 }
333 }
334 if (keepon)
335 /* multisecs v and w have no domain in common; mark */
336 /* all domains adjacent to w and put w in cluster u */
337 { for (j = jstart; j < jstop; j++)
338 { x = adjncy[j];
339 if (vtype[x] == 1) tmp[rep[x]] = flag;
340 }
341 queue[qtail++] = w;
342 rep[w] = u;
343 vtype[w] = -2;
344 }
345 }
346 }
347 }
348
349 /* clear tmp vector for next round */
350 flag++;
351 }
352
353 /* ------------------------------------
354 reset vtype and free working storage
355 ------------------------------------ */
356 for (u = 0; u < nvtx; u++)
357 if (vtype[u] == -2)
358 vtype[u] = 2;
359 free(tmp); free(queue);
360}
361
362
363/*****************************************************************************
364******************************************************************************/
367{ domdec_t *dd;
368 PORD_INT *xadj, *adjncy, *vwght, *xadjdd, *adjncydd, *vwghtdd, *vtypedd;
369 PORD_INT *tmp, *bin, nvtx, nedges, nvtxdd, nedgesdd, ndom, domwght, flag;
370 PORD_INT i, j, jstart, jstop, u, v, w;
371
372 nvtx = G->nvtx;
373 nedges = G->nedges;
374 xadj = G->xadj;
375 adjncy = G->adjncy;
376 vwght = G->vwght;
377
378 /* ------------------------
379 allocate working storage
380 ------------------------ */
381 mymalloc(tmp, nvtx, PORD_INT);
382 mymalloc(bin, nvtx, PORD_INT);
383 for (u = 0; u < nvtx; u++)
384 { tmp[u] = -1;
385 bin[u] = -1;
386 }
387
388 /* -------------------------------------------------------------
389 allocate memory for the dd using upper bounds nvtx and nedges
390 ------------------------------------------------------------- */
391 dd = newDomainDecomposition(nvtx, nedges);
392 xadjdd = dd->G->xadj;
393 adjncydd = dd->G->adjncy;
394 vwghtdd = dd->G->vwght;
395 vtypedd = dd->vtype;
396
397 /* -------------------------------------------------------
398 put all nodes u belonging to representative v in bin[v]
399 ------------------------------------------------------- */
400 for (u = 0; u < nvtx; u++)
401 { v = rep[u];
402 if (u != v)
403 { bin[u] = bin[v];
404 bin[v] = u;
405 }
406 }
407
408 /* ----------------------------------------------
409 and now build the initial domain decomposition
410 ---------------------------------------------- */
411 flag = 1;
412 nedgesdd = nvtxdd = 0;
413 ndom = domwght = 0;
414 for (u = 0; u < nvtx; u++)
415 if (rep[u] == u)
416 { xadjdd[nvtxdd] = nedgesdd;
417 vtypedd[nvtxdd] = vtype[u];
418 vwghtdd[nvtxdd] = 0;
419 tmp[u] = flag;
420
421 /* find all cluster that are adjacent to u in dom. dec. */
422 v = u;
423 do
424 { map[v] = nvtxdd;
425 vwghtdd[nvtxdd] += vwght[v];
426 jstart = xadj[v];
427 jstop = xadj[v+1];
428 for (j = jstart; j < jstop; j++)
429 { w = adjncy[j];
430 if ((vtype[w] != vtype[u]) && (tmp[rep[w]] != flag))
431 { tmp[rep[w]] = flag;
432 adjncydd[nedgesdd++] = rep[w];
433 }
434 }
435 v = bin[v];
436 } while (v != -1);
437
438 if (vtypedd[nvtxdd] == 1)
439 { ndom++;
440 domwght += vwghtdd[nvtxdd];
441 }
442 nvtxdd++;
443 flag++;
444 }
445
446 /* --------------------------------------------
447 finalize the new domain decomposition object
448 -------------------------------------------- */
449 xadjdd[nvtxdd] = nedgesdd;
450 dd->G->nvtx = nvtxdd;
451 dd->G->nedges = nedgesdd;
452 dd->G->type = WEIGHTED;
453 dd->G->totvwght = G->totvwght;
454 for (i = 0; i < nedgesdd; i++)
455 adjncydd[i] = map[adjncydd[i]];
456 for (u = 0; u < nvtxdd; u++)
457 dd->color[u] = dd->map[u] = -1;
458 dd->ndom = ndom;
459 dd->domwght = domwght;
460
461 /* -------------------------------
462 free working storage and return
463 ------------------------------- */
464 free(tmp); free(bin);
465 return(dd);
466}
467
468
469/*****************************************************************************
470******************************************************************************/
473{ domdec_t *dd;
474 PORD_INT *xadj, *adjncy, *vwght, *vtxlist, *vtype, *key, *rep;
475 PORD_INT nvtx, deg, u, i, istart, istop;
476
477 nvtx = G->nvtx;
478 xadj = G->xadj;
479 adjncy = G->adjncy;
480 vwght = G->vwght;
481
482 /* ---------------------------------------------------------
483 sort the vertices in G in ascending order of their degree
484 --------------------------------------------------------- */
485 mymalloc(vtxlist, nvtx, PORD_INT);
486 mymalloc(key, nvtx, PORD_INT);
487 for (u = 0; u < nvtx; u++)
488 { vtxlist[u] = u;
489 istart = xadj[u];
490 istop = xadj[u+1];
491 switch(G->type)
492 { case UNWEIGHTED:
493 deg = istop - istart;
494 break;
495 case WEIGHTED:
496 deg = 0;
497 for (i = istart; i < istop; i++)
498 deg += vwght[adjncy[i]];
499 break;
500 default:
501 fprintf(stderr, "\nError in function constructDomainDecomposition\n"
502 " unrecognized graph type %d\n", G->type);
503 quit();
504 }
505 key[u] = deg;
506 }
507 distributionCounting(nvtx, vtxlist, key);
508 free(key);
509
510 /* -------------------------------------------------------------
511 build initial domains and cluster multisecs that do not share
512 a common domain
513 ------------------------------------------------------------- */
514 mymalloc(vtype, nvtx, PORD_INT);
515 mymalloc(rep, nvtx, PORD_INT);
516 for (u = 0; u < nvtx; u++)
517 { vtype[u] = 0;
518 rep[u] = u;
519 }
520 buildInitialDomains(G, vtxlist, vtype, rep);
521 mergeMultisecs(G, vtype, rep);
522 free(vtxlist);
523
524 /* --------------------------------------------------
525 finally, build the domain decomposition and return
526 -------------------------------------------------- */
527 dd = initialDomainDecomposition(G, map, vtype, rep);
528 free(vtype); free(rep);
529 return(dd);
530}
531
532
533/*****************************************************************************
534******************************************************************************/
535void
536computePriorities(domdec_t *dd, PORD_INT *msvtxlist, PORD_INT *key, PORD_INT scoretype)
537{ PORD_INT *xadj, *adjncy, *vwght, *marker;
538 PORD_INT nvtx, nlist, k, weight, deg, u, v, w;
539 PORD_INT i, istart, istop, j, jstart, jstop;
540
541 nvtx = dd->G->nvtx;
542 xadj = dd->G->xadj;
543 adjncy = dd->G->adjncy;
544 vwght = dd->G->vwght;
545 marker = dd->map;
546 nlist = nvtx - dd->ndom;
547
548 switch(scoretype)
549 { case QMRDV: /* maximal relative decrease of variables in quotient graph */
550 for (k = 0; k < nlist; k++)
551 { u = msvtxlist[k];
552 weight = vwght[u];
553 istart = xadj[u];
554 istop = xadj[u+1];
555 for (i = istart; i < istop; i++)
556 weight += vwght[adjncy[i]];
557 key[u] = weight / vwght[u];
558 }
559 break;
560
561 case QMD: /* ----------------------- minimum degree in quotient graph */
562 for (k = 0; k < nlist; k++)
563 { u = msvtxlist[k];
564 marker[u] = -1;
565 }
566 for (k = 0; k < nlist; k++)
567 { u = msvtxlist[k];
568 marker[u] = u;
569 deg = 0;
570 istart = xadj[u];
571 istop = xadj[u+1];
572 for (i = istart; i < istop; i++)
573 { v = adjncy[i];
574 jstart = xadj[v];
575 jstop = xadj[v+1];
576 for (j = jstart; j < jstop; j++)
577 { w = adjncy[j];
578 if (marker[w] != u)
579 { marker[w] = u;
580 deg += vwght[w];
581 }
582 }
583 }
584 key[u] = deg;
585 }
586 break;
587
588 case QRAND: /* ------------------------------------------------- random */
589 for (k = 0; k < nlist; k++)
590 { u = msvtxlist[k];
591 key[u] = myrandom(nvtx);
592 }
593 break;
594
595 default:
596 fprintf(stderr, "\nError in internal function computePriorities\n"
597 " unrecognized node selection strategy %d\n", scoretype);
598 quit();
599 }
600}
601
602
603/*****************************************************************************
604******************************************************************************/
605void
607{ PORD_INT *xadj, *adjncy, *vtype;
608 PORD_INT nvtx, nlist, keepon, u, v, w, k, i, istart, istop;
609
610 nvtx = dd->G->nvtx;
611 xadj = dd->G->xadj;
612 adjncy = dd->G->adjncy;
613 vtype = dd->vtype;
614 nlist = nvtx - dd->ndom;
615
616 /* -------------------------------------------------------
617 eliminate multisecs according to the order in msvtxlist
618 ------------------------------------------------------- */
619 for (k = 0; k < nlist; k++)
620 { u = msvtxlist[k];
621 istart = xadj[u];
622 istop = xadj[u+1];
623 keepon = TRUE;
624 for (i = istart; i < istop; i++)
625 { v = adjncy[i];
626 if (rep[v] != v) /* domain already absorbed by an eliminated */
627 { keepon = FALSE; /* multisec => multisec u cannot be deleted */
628 break;
629 }
630 }
631 if (keepon)
632 { vtype[u] = 3;
633 for (i = istart; i < istop; i++)
634 { v = adjncy[i];
635 rep[v] = u;
636 }
637 }
638 }
639
640 /* ------------------------------------------------------------
641 eliminate all multisecs that are adjacent to only one domain
642 ------------------------------------------------------------ */
643 for (k = 0; k < nlist; k++)
644 { u = msvtxlist[k];
645 if (vtype[u] == 2)
646 { v = -1;
647 istart = xadj[u];
648 istop = xadj[u+1];
649 for (i = istart; i < istop; i++)
650 { w = adjncy[i];
651 if (v == -1)
652 v = rep[w]; /* u adjacent to domain v = rep[w] */
653 else if (v != rep[w])
654 { v = -1; /* u adjacent to another domain */
655 break;
656 }
657 }
658 if (v != -1) /* u absorbed by domain v */
659 { vtype[u] = 4;
660 rep[u] = v;
661 }
662 }
663 }
664}
665
666
667/*****************************************************************************
668******************************************************************************/
669void
671{ PORD_INT *xadj, *adjncy, *vtype, *tmp, *bin, *checksum, *next, *key;
672 PORD_INT nvtx, nlist, flag, keepon, deg, chk, ulast, u, v, k, i, istart, istop;
673
674 nvtx = dd->G->nvtx;
675 xadj = dd->G->xadj;
676 adjncy = dd->G->adjncy;
677 vtype = dd->vtype;
678 nlist = nvtx - dd->ndom;
679 checksum = dd->map;
680
681 /* ------------------------
682 allocate working storage
683 ------------------------ */
684 mymalloc(tmp, nvtx, PORD_INT);
685 mymalloc(bin, nvtx, PORD_INT);
686 mymalloc(next, nvtx, PORD_INT);
687 mymalloc(key, nvtx, PORD_INT);
688 for (u = 0; u < nvtx; u++)
689 { tmp[u] = -1;
690 bin[u] = -1;
691 }
692
693 /* -------------------------------------------------------------------
694 compute checksums for all unelim./unabsorbed multisecs in msvtxlist
695 ------------------------------------------------------------------- */
696 flag = 1;
697 for (k = 0; k < nlist; k++)
698 { u = msvtxlist[k];
699 if (vtype[u] == 2)
700 { deg = chk = 0;
701 istart = xadj[u];
702 istop = xadj[u+1];
703 for (i = istart; i < istop; i++)
704 { v = adjncy[i];
705 if (tmp[rep[v]] != flag)
706 { tmp[rep[v]] = flag;
707 chk += rep[v];
708 deg++;
709 }
710 }
711 chk = chk % nvtx;
712 checksum[u] = chk;
713 key[u] = deg;
714 next[u] = bin[chk];
715 bin[chk] = u;
716 flag++;
717 }
718 }
719
720 /* ---------------------------------
721 merge indistinguishable multisecs
722 --------------------------------- */
723 for (k = 0; k < nlist; k++)
724 { u = msvtxlist[k];
725 if (vtype[u] == 2)
726 { chk = checksum[u];
727 v = bin[chk]; /* examine all multisecs in bin[hash] */
728 bin[chk] = -1; /* do this only once */
729 while (v != -1)
730 { istart = xadj[v];
731 istop = xadj[v+1];
732 for (i = istart; i < istop; i++)
733 tmp[rep[adjncy[i]]] = flag;
734 ulast = v; /* v is principal and u is a potiential */
735 u = next[v]; /* nonprincipal variable */
736 while (u != -1)
737 { keepon = TRUE;
738 if (key[u] != key[v])
739 keepon = FALSE;
740 if (keepon)
741 { istart = xadj[u];
742 istop = xadj[u+1];
743 for (i = istart; i < istop; i++)
744 if (tmp[rep[adjncy[i]]] != flag)
745 { keepon = FALSE;
746 break;
747 }
748 }
749 if (keepon) /* found it! mark u as nonprincipal */
750 { rep[u] = v;
751 /* printf(" >> mapping %d onto %d\n", u, v); */
752 vtype[u] = 4;
753 u = next[u];
754 next[ulast] = u; /* remove u from bin */
755 }
756 else /* failed */
757 { ulast = u;
758 u = next[u];
759 }
760 }
761 v = next[v]; /* no more variables can be absorbed by v */
762 flag++; /* clear tmp vector for next round */
763 }
764 }
765 }
766
767 /* --------------------
768 free working storage
769 -------------------- */
770 free(tmp); free(bin);
771 free(next); free(key);
772}
773
774
775/*****************************************************************************
776******************************************************************************/
779{ domdec_t *dd2;
780 PORD_INT *xadjdd1, *adjncydd1, *vwghtdd1, *vtypedd1, *mapdd1;
781 PORD_INT *xadjdd2, *adjncydd2, *vwghtdd2, *vtypedd2;
782 PORD_INT *tmp, *bin, nvtxdd1, nedgesdd1, nvtxdd2, nedgesdd2;
783 PORD_INT ndom, domwght, flag, u, v, w, i, istart, istop;
784
785 nvtxdd1 = dd1->G->nvtx;
786 nedgesdd1 = dd1->G->nedges;
787 xadjdd1 = dd1->G->xadj;
788 adjncydd1 = dd1->G->adjncy;
789 vwghtdd1 = dd1->G->vwght;
790 vtypedd1 = dd1->vtype;
791 mapdd1 = dd1->map;
792
793 /* ------------------------
794 allocate working storage
795 ------------------------ */
796 mymalloc(tmp, nvtxdd1, PORD_INT);
797 mymalloc(bin, nvtxdd1, PORD_INT);
798 for (u = 0; u < nvtxdd1; u++)
799 { tmp[u] = -1;
800 bin[u] = -1;
801 }
802
803 /* ------------------------------------------------------------
804 allocate memory using the upper bounds nvtxdd1 and nedgesdd1
805 ------------------------------------------------------------ */
806 dd2 = newDomainDecomposition(nvtxdd1, nedgesdd1);
807 xadjdd2 = dd2->G->xadj;
808 adjncydd2 = dd2->G->adjncy;
809 vwghtdd2 = dd2->G->vwght;
810 vtypedd2 = dd2->vtype;
811
812 /* -------------------------------------------------------
813 put all nodes u belonging to representative v in bin[v]
814 ------------------------------------------------------- */
815 for (u = 0; u < nvtxdd1; u++)
816 { v = rep[u];
817 if (u != v)
818 { bin[u] = bin[v];
819 bin[v] = u;
820 }
821 }
822
823 /* ----------------------------------------------
824 and now build the coarser domain decomposition
825 ---------------------------------------------- */
826 flag = 1;
827 nvtxdd2 = nedgesdd2 = 0;
828 ndom = domwght = 0;
829 for (u = 0; u < nvtxdd1; u++)
830 if (rep[u] == u)
831 { xadjdd2[nvtxdd2] = nedgesdd2;
832 vwghtdd2[nvtxdd2] = 0;
833 vtypedd2[nvtxdd2] = vtypedd1[u];
834 if (vtypedd2[nvtxdd2] == 3)
835 vtypedd2[nvtxdd2] = 1;
836 tmp[u] = flag;
837
838 /* find all cluster that are adjacent to u in dom. dec. */
839 v = u;
840 do
841 { mapdd1[v] = nvtxdd2;
842 vwghtdd2[nvtxdd2] += vwghtdd1[v];
843 if ((vtypedd1[v] == 1) || (vtypedd1[v] == 2))
844 { istart = xadjdd1[v];
845 istop = xadjdd1[v+1];
846 for (i = istart; i < istop; i++)
847 { w = adjncydd1[i];
848 if (tmp[rep[w]] != flag)
849 { tmp[rep[w]] = flag;
850 adjncydd2[nedgesdd2++] = rep[w];
851 }
852 }
853 }
854 v = bin[v];
855 } while (v != -1);
856
857 if (vtypedd2[nvtxdd2] == 1)
858 { ndom++;
859 domwght += vwghtdd2[nvtxdd2];
860 }
861 nvtxdd2++;
862 flag++;
863 }
864
865 /* --------------------------------------------
866 finalize the new domain decomposition object
867 -------------------------------------------- */
868 xadjdd2[nvtxdd2] = nedgesdd2;
869 dd2->G->nvtx = nvtxdd2;
870 dd2->G->nedges = nedgesdd2;
871 dd2->G->type = WEIGHTED;
872 dd2->G->totvwght = dd1->G->totvwght;
873 for (i = 0; i < nedgesdd2; i++)
874 adjncydd2[i] = mapdd1[adjncydd2[i]];
875 for (u = 0; u < nvtxdd2; u++)
876 dd2->color[u] = dd2->map[u] = -1;
877 dd2->ndom = ndom;
878 dd2->domwght = domwght;
879
880 /* --------------------------
881 set back node types in dd1
882 -------------------------- */
883 for (u = 0; u < nvtxdd1; u++)
884 if ((vtypedd1[u] == 3) || (vtypedd1[u] == 4))
885 vtypedd1[u] = 2;
886
887 /* -------------------------------
888 free working storage and return
889 ------------------------------- */
890 free(tmp); free(bin);
891 return(dd2);
892}
893
894
895/*****************************************************************************
896******************************************************************************/
897void
899{ domdec_t *dd2;
900 PORD_INT *msvtxlist, *rep, *key;
901 PORD_INT nvtxdd1, nlist, u;
902
903 nvtxdd1 = dd1->G->nvtx;
904 mymalloc(msvtxlist, nvtxdd1, PORD_INT);
905 mymalloc(rep, nvtxdd1, PORD_INT);
906 mymalloc(key, nvtxdd1, PORD_INT);
907
908 /* ---------------
909 initializations
910 --------------- */
911 nlist = 0;
912 for (u = 0; u < nvtxdd1; u++)
913 { if (dd1->vtype[u] == 2)
914 msvtxlist[nlist++] = u;
915 rep[u] = u;
916 }
917
918 /* -------------------------------------
919 compute priorities and sort multisecs
920 ------------------------------------- */
921 computePriorities(dd1, msvtxlist, key, scoretype);
922 distributionCounting(nlist, msvtxlist, key);
923
924 /* ----------------------------------------------------------
925 eliminate multisecs and build coarser domain decomposition
926 ---------------------------------------------------------- */
927 eliminateMultisecs(dd1, msvtxlist, rep);
928 findIndMultisecs(dd1, msvtxlist, rep);
929 dd2 = coarserDomainDecomposition(dd1, rep);
930
931 /* -----------------------------------
932 append coarser domain decomposition
933 ----------------------------------- */
934 dd1->next = dd2;
935 dd2->prev = dd1;
936
937 free(msvtxlist);
938 free(rep);
939 free(key);
940}
#define TRUE
Definition cblas_test.h:10
#define FALSE
Definition cblas_test.h:14
#define QRAND
Definition const.h:37
#define QMRDV
Definition const.h:36
#define BLACK
Definition const.h:63
#define WHITE
Definition const.h:64
#define WEIGHTED
Definition const.h:20
#define QMD
Definition const.h:35
#define UNWEIGHTED
Definition const.h:19
#define GRAY
Definition const.h:62
domdec_t * initialDomainDecomposition(graph_t *G, PORD_INT *map, PORD_INT *vtype, PORD_INT *rep)
Definition ddcreate.c:366
void freeDomainDecomposition(domdec_t *dd)
Definition ddcreate.c:120
void buildInitialDomains(graph_t *G, PORD_INT *vtxlist, PORD_INT *vtype, PORD_INT *rep)
Definition ddcreate.c:224
void shrinkDomainDecomposition(domdec_t *dd1, PORD_INT scoretype)
Definition ddcreate.c:898
domdec_t * constructDomainDecomposition(graph_t *G, PORD_INT *map)
Definition ddcreate.c:472
domdec_t * newDomainDecomposition(PORD_INT nvtx, PORD_INT nedges)
Definition ddcreate.c:100
void mergeMultisecs(graph_t *G, PORD_INT *vtype, PORD_INT *rep)
Definition ddcreate.c:280
domdec_t * coarserDomainDecomposition(domdec_t *dd1, PORD_INT *rep)
Definition ddcreate.c:778
void printDomainDecomposition(domdec_t *dd)
Definition ddcreate.c:133
void eliminateMultisecs(domdec_t *dd, PORD_INT *msvtxlist, PORD_INT *rep)
Definition ddcreate.c:606
void checkDomainDecomposition(domdec_t *dd)
Definition ddcreate.c:163
void computePriorities(domdec_t *dd, PORD_INT *msvtxlist, PORD_INT *key, PORD_INT scoretype)
Definition ddcreate.c:536
void findIndMultisecs(domdec_t *dd, PORD_INT *msvtxlist, PORD_INT *rep)
Definition ddcreate.c:670
#define myrandom(range)
Definition macros.h:37
#define quit()
Definition macros.h:64
#define mymalloc(ptr, nr, type)
Definition macros.h:23
graph_t * newGraph(PORD_INT, PORD_INT)
Definition graph.c:50
void freeGraph(graph_t *)
Definition graph.c:73
void distributionCounting(PORD_INT, PORD_INT *, PORD_INT *)
Definition sort.c:186
*fortran !University of Stuttgart All rights reserved Inc All rights reserved ! $COPYRIGHT$ !Additional copyrights may follow ! $HEADER$ !WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING !Do ***not ***copy this file to the directory where your Fortran !fortran application is compiled unless it is absolutely necessary !Most !modern Fortran compilers now support the I command line flag
Definition mpif.h:26
struct _domdec * prev
Definition types.h:60
struct _domdec * next
Definition types.h:60
PORD_INT * vtype
Definition types.h:56
PORD_INT ndom
Definition types.h:54
PORD_INT cwght[3]
Definition types.h:58
PORD_INT domwght
Definition types.h:55
PORD_INT * color
Definition types.h:57
graph_t * G
Definition types.h:53
PORD_INT * map
Definition types.h:59
PORD_INT totvwght
Definition types.h:34
PORD_INT * xadj
Definition types.h:35
PORD_INT type
Definition types.h:33
PORD_INT nedges
Definition types.h:32
PORD_INT nvtx
Definition types.h:31
PORD_INT * vwght
Definition types.h:37
PORD_INT * adjncy
Definition types.h:36
#define PORD_INT
Definition types.h:20
struct _graph graph_t
struct _domdec domdec_t