Actual source code: localcolor.c
petsc-dev 2014-02-02
1: #include <petsc-private/matimpl.h> /*I "petscmat.h" I*/
2: #include <petscsf.h>
8: PETSC_EXTERN PetscErrorCode MatColoringLocalColor(MatColoring mc,PetscSF etoc,PetscSF etor,PetscReal *wts,ISColoringValue *color, ISColoringValue *maxcolor)
9: {
10: PetscInt nrows,ncols,ncolentries,nrowentries,idx,neighoffset;
11: PetscInt i,j,k;
12: PetscInt dist = mc->dist;
13: PetscInt totalcolors;
14: PetscBool *colormask;
15: PetscErrorCode ierr;
16: PetscBool *rowseen,*colseen;
17: const PetscInt *rowdegrees;
18: PetscInt *rowoffsets;
19: const PetscInt *coldegrees;
20: PetscInt *coloffsets;
21: PetscInt offset;
22: PetscInt *ll_ptr;
23: PetscInt *ll_idx;
24: PetscReal *swts;
25: PetscInt *sidx;
26: PetscInt unused;
27: PetscInt rowlist,collist;
28: PetscInt swp;
29: PetscMPIInt rank;
30: const PetscSFNode *colentries,*rowentries;
33: MPI_Comm_rank(PetscObjectComm((PetscObject)mc),&rank);
35: PetscSFGetGraph(etoc,&ncols,&ncolentries,NULL,&colentries);
36: PetscSFGetGraph(etor,&nrows,&nrowentries,NULL,&rowentries);
38: PetscMalloc6(nrows,&rowseen,ncols,&colseen,ncols,&coloffsets,nrows,&rowoffsets,2*ncols,&ll_ptr,2*ncols,&ll_idx);
39: PetscMalloc2(ncols,&sidx,ncols,&swts);
41: PetscSFComputeDegreeBegin(etoc,&rowdegrees);
42: PetscSFComputeDegreeEnd(etoc,&rowdegrees);
44: PetscSFComputeDegreeBegin(etor,&coldegrees);
45: PetscSFComputeDegreeEnd(etor,&coldegrees);
47: /* sort by weight */
48: for (i=0;i<ncols;i++) {
49: sidx[i] = i;
50: swts[i] = wts[i];
51: }
53: PetscSortRealWithPermutation(ncols,swts,sidx);
54: for (i=0;i<ncols/2;i++) {
55: swp = sidx[i];
56: sidx[i] = sidx[ncols-1-i];
57: sidx[ncols-1-i] = swp;
58: }
60: /* set up the "unused" linked list */
61: unused = 0;
62: ll_ptr[2*ncols-1] = -1;
63: for (i=0;i<2*ncols-1;i++) {
64: ll_ptr[i] = i+1;
65: }
67: /* initialize the offsets */
68: offset=0;
69: for (i=0;i<ncols;i++) {
70: coloffsets[i] = offset;
71: offset+=coldegrees[i];
72: colseen[i] = PETSC_FALSE;
73: }
74: offset=0;
75: for (i=0;i<nrows;i++) {
76: rowoffsets[i] = offset;
77: offset+=rowdegrees[i];
78: rowseen[i] = PETSC_FALSE;
79: }
81: /* discover the maximum current color */
82: totalcolors = 1;
83: for (i=0;i<ncols;i++) {
84: if (color[i] > totalcolors-1 && color[i] != IS_COLORING_MAX) totalcolors = color[i]+1;
85: }
86: if (totalcolors < 10) totalcolors=10;
87: PetscMalloc(sizeof(PetscBool)*totalcolors,&colormask);
89: /* alternate between rows and columns to get the distance k minimum coloring */
90: for (i=0;i<ncols;i++) {
91: collist = -1;
92: rowlist = -1;
93: if (color[sidx[i]] == IS_COLORING_MAX) {
94: for (j=0;j<totalcolors;j++) colormask[j] = PETSC_FALSE;
95: swp = unused;
96: unused = ll_ptr[unused];
97: ll_ptr[swp] = collist;
98: ll_idx[swp] = sidx[i];
99: collist = swp;
100: colseen[sidx[i]] = PETSC_TRUE;
101: for (k=0;k<=dist;k++) {
102: if (k % 2 == 0) {
103: while (collist >= 0) {
104: if (k != dist) {
105: for (j=0;j<coldegrees[ll_idx[collist]];j++) {
106: neighoffset = coloffsets[ll_idx[collist]]+j;
107: idx = colentries[neighoffset].index;
108: if (colentries[neighoffset].rank == rank && !rowseen[idx]) {
109: swp = unused;
110: unused = ll_ptr[unused];
111: ll_ptr[swp] = rowlist;
112: ll_idx[swp] = idx;
113: rowlist = swp;
114: rowseen[idx] = PETSC_TRUE;
115: }
116: }
117: }
118: if (color[ll_idx[collist]] != IS_COLORING_MAX) colormask[color[ll_idx[collist]]] = PETSC_TRUE;
119: colseen[ll_idx[collist]] = PETSC_FALSE;
120: swp = collist;
121: collist = ll_ptr[collist];
122: ll_ptr[swp] = unused;
123: unused = swp;
124: }
125: } else {
126: while (rowlist >= 0) {
127: if (k != dist) {
128: for (j=0;j<rowdegrees[ll_idx[rowlist]];j++) {
129: neighoffset = rowoffsets[ll_idx[rowlist]]+j;
130: idx = rowentries[neighoffset].index;
131: if (rowentries[neighoffset].rank == rank && !colseen[idx]) {
132: swp = unused;
133: unused = ll_ptr[unused];
134: ll_ptr[swp] = collist;
135: ll_idx[swp] = idx;
136: collist = swp;
137: colseen[idx] = PETSC_TRUE;
138: }
139: }
140: }
141: if (color[ll_idx[rowlist]] != IS_COLORING_MAX) colormask[color[ll_idx[rowlist]]] = PETSC_TRUE;
142: rowseen[ll_idx[rowlist]] = PETSC_FALSE;
143: swp = rowlist;
144: rowlist = ll_ptr[rowlist];
145: ll_ptr[swp] = unused;
146: unused = swp;
147: }
148: }
149: }
150: color[sidx[i]] = totalcolors;
151: for (k=0;k<totalcolors;k++) {
152: if (!colormask[k]) {color[sidx[i]] = k; break;}
153: }
154: if (color[sidx[i]] >= mc->maxcolors && mc->maxcolors > 0) color[sidx[i]] = mc->maxcolors;
155: if (color[sidx[i]] > *maxcolor) *maxcolor = color[sidx[i]];
156: if (color[sidx[i]] > totalcolors-1) {
157: totalcolors *= 2;
158: PetscFree(colormask);
159: PetscMalloc(sizeof(PetscBool)*totalcolors,&colormask);
160: }
161: }
162: if (collist != -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in local coloring BFS -- column queue still has %d\n",collist);
163: if (rowlist != -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in local coloring BFS -- row queue still has %d\n",rowlist);
164: }
165: for (i=0;i<ncols;i++) {
166: if (colseen[i]) {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in local coloring BFS -- column %d still seen\n",i);}
167: }
168: for (i=0;i<nrows;i++) {
169: if (rowseen[i]) {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in local coloring BFS -- row %d still seen\n",i);}
170: }
172: PetscFree6(rowseen,colseen,coloffsets,rowoffsets,ll_ptr,ll_idx);
173: PetscFree2(sidx,swts);
174: PetscFree(colormask);
176: return(0);
177: }
181: PETSC_EXTERN PetscErrorCode MatColoringDiscoverBoundary(MatColoring mc,PetscSF etoc,PetscSF etor,PetscInt *nboundary,PetscInt **boundary)
182: {
183: PetscInt nrows,ncols,ncolentries,nrowentries,idx,bidx,neighoffset;
184: PetscInt i,j,k;
185: PetscInt dist = mc->dist;
186: PetscBool onBoundary;
187: PetscErrorCode ierr;
188: PetscBool *rowseen,*colseen;
189: const PetscInt *rowdegrees;
190: PetscInt *rowoffsets;
191: const PetscInt *coldegrees;
192: PetscInt *coloffsets;
193: PetscInt offset;
194: PetscInt *ll_ptr;
195: PetscInt *ll_idx;
196: PetscInt unused;
197: PetscInt rowlist,collist;
198: PetscInt swp;
199: PetscMPIInt rank;
200: const PetscSFNode *colentries,*rowentries;
203: *nboundary = 0;
204: MPI_Comm_rank(PetscObjectComm((PetscObject)mc),&rank);
206: PetscSFGetGraph(etoc,&ncols,&ncolentries,NULL,&colentries);
207: PetscSFGetGraph(etor,&nrows,&nrowentries,NULL,&rowentries);
209: PetscMalloc6(nrows,&rowseen,
210: ncols,&colseen,
211: ncols,&coloffsets,
212: nrows,&rowoffsets,
213: 2*ncols,&ll_ptr,
214: 2*ncols,&ll_idx);
216: PetscSFComputeDegreeBegin(etoc,&rowdegrees);
217: PetscSFComputeDegreeEnd(etoc,&rowdegrees);
219: PetscSFComputeDegreeBegin(etor,&coldegrees);
220: PetscSFComputeDegreeEnd(etor,&coldegrees);
222: /* set up the "unused" linked list -- double the size of the number of items as in tiny or large distance cases we may have a clique */
223: unused = 0;
224: ll_ptr[2*ncols-1] = -1;
225: for (i=0;i<2*ncols-1;i++) {
226: ll_ptr[i] = i+1;
227: }
229: /* initialize the offsets */
230: offset=0;
231: for (i=0;i<ncols;i++) {
232: coloffsets[i] = offset;
233: offset+=coldegrees[i];
234: colseen[i] = PETSC_FALSE;
235: }
236: offset=0;
237: for (i=0;i<nrows;i++) {
238: rowoffsets[i] = offset;
239: offset+=rowdegrees[i];
240: rowseen[i] = PETSC_FALSE;
241: }
243: /* count the number of boundary nodes */
244: for (i=0;i<ncols;i++) {
245: onBoundary = PETSC_FALSE;
246: collist = -1;
247: rowlist = -1;
248: swp = unused;
249: unused = ll_ptr[unused];
250: ll_ptr[swp] = collist;
251: ll_idx[swp] = i;
252: collist = swp;
253: colseen[i] = PETSC_TRUE;
254: for (k=0;k<=dist;k++) {
255: if (k % 2 == 0) {
256: while (collist >= 0) {
257: if (k != dist) {
258: for (j=0;j<coldegrees[ll_idx[collist]];j++) {
259: neighoffset = coloffsets[ll_idx[collist]]+j;
260: idx = colentries[neighoffset].index;
261: if (colentries[neighoffset].rank == rank) {
262: if (!rowseen[idx] && !onBoundary) {
263: swp = unused;
264: unused = ll_ptr[unused];
265: ll_ptr[swp] = rowlist;
266: rowlist = swp;
267: ll_idx[swp] = idx;
268: rowseen[idx] = PETSC_TRUE;
269: }
270: } else {
271: onBoundary = PETSC_TRUE;
272: }
273: }
274: }
275: colseen[ll_idx[collist]] = PETSC_FALSE;
276: swp = collist;
277: collist = ll_ptr[collist];
278: ll_ptr[swp] = unused;
279: unused = swp;
280: }
281: } else {
282: while (rowlist >= 0) {
283: if (k != dist) {
284: for (j=0;j<rowdegrees[ll_idx[rowlist]];j++) {
285: neighoffset = rowoffsets[ll_idx[rowlist]]+j;
286: if (rowentries[neighoffset].rank == rank) {
287: idx = rowentries[neighoffset].index;
288: if (!colseen[idx] && !onBoundary) {
289: swp = unused;
290: unused = ll_ptr[unused];
291: ll_ptr[swp] = collist;
292: ll_idx[swp] = idx;
293: colseen[idx] = PETSC_TRUE;
294: collist = swp;
295: }
296: } else {
297: onBoundary = PETSC_TRUE;
298: }
299: }
300: }
301: rowseen[ll_idx[rowlist]] = PETSC_FALSE;
302: swp = rowlist;
303: rowlist = ll_ptr[rowlist];
304: ll_ptr[swp] = unused;
305: unused = swp;
306: }
307: }
308: }
309: if (onBoundary) {(*nboundary)++;}
310: if (collist != -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in boundary count BFS -- column queue still has %d\n",collist);
311: if (rowlist != -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in boundary count BFS -- row queue still has %d\n",collist);
312: }
313: for (i=0;i<ncols;i++) {
314: if (colseen[i]) {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in boundary count BFS -- column %d still seen\n",i);}
315: }
316: for (i=0;i<nrows;i++) {
317: if (rowseen[i]) {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in boundary count BFS -- row %d still seen\n",i);}
318: }
320: PetscMalloc(sizeof(PetscInt)*(*nboundary),boundary);
322: /* set the boundary nodes */
323: bidx=0;
324: for (i=0;i<ncols;i++) {
325: onBoundary = PETSC_FALSE;
326: collist = -1;
327: rowlist = -1;
328: swp = unused;
329: unused = ll_ptr[unused];
330: ll_ptr[swp] = collist;
331: ll_idx[swp] = i;
332: collist = swp;
333: colseen[i] = PETSC_TRUE;
334: for (k=0;k<=dist;k++) {
335: if (k % 2 == 0) {
336: while (collist >= 0) {
337: if (k != dist) {
338: for (j=0;j<coldegrees[ll_idx[collist]];j++) {
339: neighoffset = coloffsets[ll_idx[collist]]+j;
340: idx = colentries[neighoffset].index;
341: if (colentries[neighoffset].rank == rank) {
342: if (!rowseen[idx] && !onBoundary) {
343: swp = unused;
344: unused = ll_ptr[unused];
345: ll_ptr[swp] = rowlist;
346: rowlist = swp;
347: ll_idx[swp] = idx;
348: rowseen[idx] = PETSC_TRUE;
349: }
350: } else {
351: onBoundary = PETSC_TRUE;
352: }
353: }
354: }
355: colseen[ll_idx[collist]] = PETSC_FALSE;
356: swp = collist;
357: collist = ll_ptr[collist];
358: ll_ptr[swp] = unused;
359: unused = swp;
360: }
361: } else {
362: while (rowlist >= 0) {
363: if (k != dist) {
364: for (j=0;j<rowdegrees[ll_idx[rowlist]];j++) {
365: neighoffset = rowoffsets[ll_idx[rowlist]]+j;
366: if (rowentries[neighoffset].rank == rank) {
367: idx = rowentries[neighoffset].index;
368: if (!colseen[idx] && !onBoundary) {
369: swp = unused;
370: unused = ll_ptr[unused];
371: ll_ptr[swp] = collist;
372: ll_idx[swp] = idx;
373: colseen[idx] = PETSC_TRUE;
374: collist = swp;
375: }
376: } else {
377: onBoundary = PETSC_TRUE;
378: }
379: }
380: }
381: rowseen[ll_idx[rowlist]] = PETSC_FALSE;
382: swp = rowlist;
383: rowlist = ll_ptr[rowlist];
384: ll_ptr[swp] = unused;
385: unused = swp;
386: }
387: }
388: }
389: if (onBoundary) {(*boundary)[bidx] = i; bidx++;}
390: }
391: for (i=0;i<ncols;i++) {
392: if (colseen[i]) {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in boundary set BFS -- column %d still seen\n",i);}
393: }
394: for (i=0;i<nrows;i++) {
395: if (rowseen[i]) {SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_NOT_CONVERGED,"Likely error in boundary set BFS -- row %d still seen\n",i);}
396: }
397: if (bidx != *nboundary) {SETERRQ(PetscObjectComm((PetscObject)mc),PETSC_ERR_NOT_CONVERGED,"Number of boundary nodes not matched");}
398: PetscFree6(rowseen,colseen,coloffsets,rowoffsets,ll_ptr,ll_idx);
399: return(0);
400: }