Actual source code: localcolor.c

petsc-dev 2014-02-02
Report Typos and Errors
  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: }