Date: 2015-10-02T22:12:52+00:00

Actual source code: greedy.c
petsc-3.6.2 2015-10-02
Report Typos and Errors

      1: #include <petsc/private/matimpl.h>      /*I "petscmat.h"  I*/
      2: #include <../src/mat/impls/aij/seq/aij.h>
      3: #include <../src/mat/impls/aij/mpi/mpiaij.h>
      4: #include <petscsf.h>

      6: typedef struct {
      7:   PetscBool symmetric;
      8: } MC_Greedy;

     12: PetscErrorCode MatColoringDestroy_Greedy(MatColoring mc)
     13: {

     17:   PetscFree(mc->data);
     18:   return(0);
     19: }

     23: PETSC_EXTERN PetscErrorCode GreedyColoringLocalDistanceOne_Private(MatColoring mc,PetscReal *wts,PetscInt *lperm,ISColoringValue *colors)
     24: {
     25:   PetscInt        i,j,k,s,e,n,no,nd,nd_global,n_global,idx,ncols,maxcolors,masksize,ccol,*mask;
     26:   PetscErrorCode  ierr;
     27:   Mat             m=mc->mat;
     28:   Mat_MPIAIJ      *aij = (Mat_MPIAIJ*)m->data;
     29:   Mat             md=NULL,mo=NULL;
     30:   const PetscInt  *md_i,*mo_i,*md_j,*mo_j;
     31:   PetscBool       isMPIAIJ,isSEQAIJ;
     32:   ISColoringValue pcol;
     33:   const PetscInt  *cidx;
     34:   PetscInt        *lcolors,*ocolors;
     35:   PetscReal       *owts=NULL;
     36:   PetscSF         sf;
     37:   PetscLayout     layout;

     40:   MatGetSize(m,&n_global,NULL);
     41:   MatGetOwnershipRange(m,&s,&e);
     42:   n=e-s;
     43:   masksize=20;
     44:   nd_global = 0;
     45:   /* get the matrix communication structures */
     46:   PetscObjectTypeCompare((PetscObject)m, MATMPIAIJ, &isMPIAIJ);
     47:   PetscObjectTypeCompare((PetscObject)m, MATSEQAIJ, &isSEQAIJ);
     48:   if (isMPIAIJ) {
     49:     /* get the CSR data for on and off diagonal portions of m */
     50:     Mat_SeqAIJ *dseq;
     51:     Mat_SeqAIJ *oseq;
     52:     md=aij->A;
     53:     dseq = (Mat_SeqAIJ*)md->data;
     54:     mo=aij->B;
     55:     oseq = (Mat_SeqAIJ*)mo->data;
     56:     md_i = dseq->i;
     57:     md_j = dseq->j;
     58:     mo_i = oseq->i;
     59:     mo_j = oseq->j;
     60:   } else if (isSEQAIJ) {
     61:     /* get the CSR data for m */
     62:     Mat_SeqAIJ *dseq;
     63:     /* no off-processor nodes */
     64:     md=m;
     65:     dseq = (Mat_SeqAIJ*)md->data;
     66:     mo=NULL;
     67:     no=0;
     68:     md_i = dseq->i;
     69:     md_j = dseq->j;
     70:     mo_i = NULL;
     71:     mo_j = NULL;
     72:   } else {
     73:     SETERRQ(PetscObjectComm((PetscObject)mc),PETSC_ERR_ARG_WRONG,"Matrix must be AIJ for greedy coloring");
     74:   }
     75:   MatColoringGetMaxColors(mc,&maxcolors);
     76:   if (mo) {
     77:     VecGetSize(aij->lvec,&no);
     78:     PetscMalloc2(no,&ocolors,no,&owts);
     79:     for(i=0;i<no;i++) {
     80:       ocolors[i]=maxcolors;
     81:     }
     82:   }

     84:   PetscMalloc1(masksize,&mask);
     85:   PetscMalloc1(n,&lcolors);
     86:   for(i=0;i<n;i++) {
     87:     lcolors[i]=maxcolors;
     88:   }
     89:   for (i=0;i<masksize;i++) {
     90:     mask[i]=-1;
     91:   }
     92:   if (mo) {
     93:     /* transfer neighbor weights */
     94:     PetscSFCreate(PetscObjectComm((PetscObject)m),&sf);
     95:     MatGetLayouts(m,&layout,NULL);
     96:     PetscSFSetGraphLayout(sf,layout,no,NULL,PETSC_COPY_VALUES,aij->garray);
     97:     PetscSFBcastBegin(sf,MPIU_REAL,wts,owts);
     98:     PetscSFBcastEnd(sf,MPIU_REAL,wts,owts);
     99:   }
    100:   while (nd_global < n_global) {
    101:     nd=n;
    102:     /* assign lowest possible color to each local vertex */
    103:     PetscLogEventBegin(Mat_Coloring_Local,mc,0,0,0);
    104:     for (i=0;i<n;i++) {
    105:       idx=lperm[i];
    106:       if (lcolors[idx] == maxcolors) {
    107:         ncols = md_i[idx+1]-md_i[idx];
    108:         cidx = &(md_j[md_i[idx]]);
    109:         for (j=0;j<ncols;j++) {
    110:           if (lcolors[cidx[j]] != maxcolors) {
    111:             ccol=lcolors[cidx[j]];
    112:             if (ccol>=masksize) {
    113:               PetscInt *newmask;
    114:               PetscMalloc1(masksize*2,&newmask);
    115:               for(k=0;k<2*masksize;k++) {
    116:                 newmask[k]=-1;
    117:               }
    118:               for(k=0;k<masksize;k++) {
    119:                 newmask[k]=mask[k];
    120:               }
    121:               PetscFree(mask);
    122:               mask=newmask;
    123:               masksize*=2;
    124:             }
    125:             mask[ccol]=idx;
    126:           }
    127:         }
    128:         if (mo) {
    129:           ncols = mo_i[idx+1]-mo_i[idx];
    130:           cidx = &(mo_j[mo_i[idx]]);
    131:           for (j=0;j<ncols;j++) {
    132:             if (ocolors[cidx[j]] != maxcolors) {
    133:               ccol=ocolors[cidx[j]];
    134:               if (ccol>=masksize) {
    135:                 PetscInt *newmask;
    136:                 PetscMalloc1(masksize*2,&newmask);
    137:                 for(k=0;k<2*masksize;k++) {
    138:                   newmask[k]=-1;
    139:                 }
    140:                 for(k=0;k<masksize;k++) {
    141:                   newmask[k]=mask[k];
    142:                 }
    143:                 PetscFree(mask);
    144:                 mask=newmask;
    145:                 masksize*=2;
    146:               }
    147:               mask[ccol]=idx;
    148:             }
    149:           }
    150:         }
    151:         for (j=0;j<masksize;j++) {
    152:           if (mask[j]!=idx) {
    153:             break;
    154:           }
    155:         }
    156:         pcol=j;
    157:         if (pcol>maxcolors)pcol=maxcolors;
    158:         lcolors[idx]=pcol;
    159:       }
    160:     }
    161:     PetscLogEventEnd(Mat_Coloring_Local,mc,0,0,0);
    162:     if (mo) {
    163:       /* transfer neighbor colors */
    164:       PetscLogEventBegin(Mat_Coloring_Comm,mc,0,0,0);
    165:       PetscSFBcastBegin(sf,MPIU_INT,lcolors,ocolors);
    166:       PetscSFBcastEnd(sf,MPIU_INT,lcolors,ocolors);
    167:       /* check for conflicts -- this is merely checking if any adjacent off-processor rows have the same color and marking the ones that are lower weight locally for changing */
    168:       for (i=0;i<n;i++) {
    169:         ncols = mo_i[i+1]-mo_i[i];
    170:         cidx = &(mo_j[mo_i[i]]);
    171:         for (j=0;j<ncols;j++) {
    172:           /* in the case of conflicts, the highest weight one stays and the others go */
    173:           if ((ocolors[cidx[j]] == lcolors[i]) && (owts[cidx[j]] > wts[i]) && lcolors[i] < maxcolors) {
    174:             lcolors[i]=maxcolors;
    175:             nd--;
    176:           }
    177:         }
    178:       }
    179:       nd_global=0;
    180:     }
    181:     MPI_Allreduce(&nd,&nd_global,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mc));
    182:   }
    183:   for (i=0;i<n;i++) {
    184:     colors[i] = (ISColoringValue)lcolors[i];
    185:   }
    186:   PetscFree(mask);
    187:   PetscFree(lcolors);
    188:   if (mo) {
    189:     PetscFree2(ocolors,owts);
    190:     PetscSFDestroy(&sf);
    191:   }
    192:   return(0);
    193: }

    199: PETSC_EXTERN PetscErrorCode GreedyColoringLocalDistanceTwo_Private(MatColoring mc,PetscReal *wts,PetscInt *lperm,ISColoringValue *colors)
    200: {
    201:   MC_Greedy       *gr = (MC_Greedy *) mc->data;
    202:   PetscInt        i,j,k,l,s,e,n,nd,nd_global,n_global,idx,ncols,maxcolors,mcol,mcol_global,nd1cols,*mask,masksize,*d1cols,*bad,*badnext,nbad,badsize,ccol,no,cbad;
    203:   Mat             m = mc->mat, mt;
    204:   Mat_MPIAIJ      *aij = (Mat_MPIAIJ*)m->data;
    205:   Mat             md=NULL,mo=NULL;
    206:   const PetscInt  *md_i,*mo_i,*md_j,*mo_j;
    207:   const PetscInt  *rmd_i,*rmo_i,*rmd_j,*rmo_j;
    208:   PetscBool       isMPIAIJ,isSEQAIJ;
    209:   PetscInt        pcol,*dcolors,*ocolors;
    210:   ISColoringValue *badidx;
    211:   const PetscInt  *cidx;
    212:   PetscReal       *owts,*colorweights;
    213:   PetscInt        *oconf,*conf;
    214:   PetscSF         sf;
    215:   PetscLayout     layout;
    216:   PetscErrorCode  ierr;

    219:   MatGetSize(m,&n_global,NULL);
    220:   MatGetOwnershipRange(m,&s,&e);
    221:   n=e-s;
    222:   nd_global = 0;
    223:   /* get the matrix communication structures */
    224:   PetscObjectTypeCompare((PetscObject)m, MATMPIAIJ, &isMPIAIJ);
    225:   PetscObjectTypeCompare((PetscObject)m, MATSEQAIJ, &isSEQAIJ);
    226:   if (isMPIAIJ) {
    227:     Mat_SeqAIJ *dseq;
    228:     Mat_SeqAIJ *oseq;
    229:     md=aij->A;
    230:     dseq = (Mat_SeqAIJ*)md->data;
    231:     mo=aij->B;
    232:     oseq = (Mat_SeqAIJ*)mo->data;
    233:     md_i = dseq->i;
    234:     md_j = dseq->j;
    235:     mo_i = oseq->i;
    236:     mo_j = oseq->j;
    237:     rmd_i = dseq->i;
    238:     rmd_j = dseq->j;
    239:     rmo_i = oseq->i;
    240:     rmo_j = oseq->j;
    241:   } else if (isSEQAIJ) {
    242:     Mat_SeqAIJ *dseq;
    243:     /* no off-processor nodes */
    244:     md=m;
    245:     dseq = (Mat_SeqAIJ*)md->data;
    246:     md_i = dseq->i;
    247:     md_j = dseq->j;
    248:     mo_i = NULL;
    249:     mo_j = NULL;
    250:     rmd_i = dseq->i;
    251:     rmd_j = dseq->j;
    252:     rmo_i = NULL;
    253:     rmo_j = NULL;
    254:   } else {
    255:     SETERRQ(PetscObjectComm((PetscObject)mc),PETSC_ERR_ARG_WRONG,"Matrix must be AIJ for greedy coloring");
    256:   }
    257:   if (!gr->symmetric) {
    258:     MatTranspose(m, MAT_INITIAL_MATRIX, &mt);
    259:     if (isSEQAIJ) {
    260:       Mat_SeqAIJ *dseq = (Mat_SeqAIJ*) mt->data;
    261:       rmd_i = dseq->i;
    262:       rmd_j = dseq->j;
    263:       rmo_i = NULL;
    264:       rmo_j = NULL;
    265:     } else SETERRQ(PetscObjectComm((PetscObject) mc), PETSC_ERR_SUP, "Nonsymmetric greedy coloring only works in serial");
    266:   }
    267:   /* create the vectors and communication structures if necessary */
    268:   no=0;
    269:   if (mo) {
    270:     VecGetLocalSize(aij->lvec,&no);
    271:     PetscSFCreate(PetscObjectComm((PetscObject)m),&sf);
    272:     MatGetLayouts(m,&layout,NULL);
    273:     PetscSFSetGraphLayout(sf,layout,no,NULL,PETSC_COPY_VALUES,aij->garray);
    274:   }
    275:   MatColoringGetMaxColors(mc,&maxcolors);
    276:   masksize=n;
    277:   nbad=0;
    278:   badsize=n;
    279:   PetscMalloc1(masksize,&mask);
    280:   PetscMalloc4(n,&d1cols,n,&dcolors,n,&conf,n,&bad);
    281:   PetscMalloc2(badsize,&badidx,badsize,&badnext);
    282:   for(i=0;i<masksize;i++) {
    283:     mask[i]=-1;
    284:   }
    285:   for (i=0;i<n;i++) {
    286:     dcolors[i]=maxcolors;
    287:     bad[i]=-1;
    288:   }
    289:   for (i=0;i<badsize;i++) {
    290:     badnext[i]=-1;
    291:   }
    292:   if (mo) {
    293:     PetscMalloc3(no,&owts,no,&oconf,no,&ocolors);
    294:     PetscSFBcastBegin(sf,MPIU_REAL,wts,owts);
    295:     PetscSFBcastEnd(sf,MPIU_REAL,wts,owts);
    296:     for (i=0;i<no;i++) {
    297:       ocolors[i]=maxcolors;
    298:     }
    299:   } else {                      /* Appease overzealous -Wmaybe-initialized */
    300:     owts = NULL;
    301:     oconf = NULL;
    302:     ocolors = NULL;
    303:   }
    304:   mcol=0;
    305:   while (nd_global < n_global) {
    306:     nd=n;
    307:     /* assign lowest possible color to each local vertex */
    308:     mcol_global=0;
    309:     PetscLogEventBegin(Mat_Coloring_Local,mc,0,0,0);
    310:     for (i=0;i<n;i++) {
    311:       idx=lperm[i];
    312:       if (dcolors[idx] == maxcolors) {
    313:         /* entries in bad */
    314:         cbad=bad[idx];
    315:         while (cbad>=0) {
    316:           ccol=badidx[cbad];
    317:           if (ccol>=masksize) {
    318:             PetscInt *newmask;
    319:             PetscMalloc1(masksize*2,&newmask);
    320:             for(k=0;k<2*masksize;k++) {
    321:               newmask[k]=-1;
    322:             }
    323:             for(k=0;k<masksize;k++) {
    324:               newmask[k]=mask[k];
    325:             }
    326:             PetscFree(mask);
    327:             mask=newmask;
    328:             masksize*=2;
    329:           }
    330:           mask[ccol]=idx;
    331:           cbad=badnext[cbad];
    332:         }
    333:         /* diagonal distance-one rows */
    334:         nd1cols=0;
    335:         ncols = rmd_i[idx+1]-rmd_i[idx];
    336:         cidx = &(rmd_j[rmd_i[idx]]);
    337:         for (j=0;j<ncols;j++) {
    338:           d1cols[nd1cols] = cidx[j];
    339:           nd1cols++;
    340:           ccol=dcolors[cidx[j]];
    341:           if (ccol != maxcolors) {
    342:             if (ccol>=masksize) {
    343:               PetscInt *newmask;
    344:               PetscMalloc1(masksize*2,&newmask);
    345:               for(k=0;k<2*masksize;k++) {
    346:                 newmask[k]=-1;
    347:               }
    348:               for(k=0;k<masksize;k++) {
    349:                 newmask[k]=mask[k];
    350:               }
    351:               PetscFree(mask);
    352:               mask=newmask;
    353:               masksize*=2;
    354:             }
    355:             mask[ccol]=idx;
    356:           }
    357:         }
    358:         /* off-diagonal distance-one rows */
    359:         if (mo) {
    360:           ncols = rmo_i[idx+1]-rmo_i[idx];
    361:           cidx = &(rmo_j[rmo_i[idx]]);
    362:           for (j=0;j<ncols;j++) {
    363:             ccol=ocolors[cidx[j]];
    364:             if (ccol != maxcolors) {
    365:               if (ccol>=masksize) {
    366:                 PetscInt *newmask;
    367:                 PetscMalloc1(masksize*2,&newmask);
    368:                 for(k=0;k<2*masksize;k++) {
    369:                   newmask[k]=-1;
    370:                 }
    371:                 for(k=0;k<masksize;k++) {
    372:                   newmask[k]=mask[k];
    373:                 }
    374:                 PetscFree(mask);
    375:                 mask=newmask;
    376:                 masksize*=2;
    377:               }
    378:               mask[ccol]=idx;
    379:             }
    380:           }
    381:         }
    382:         /* diagonal distance-two rows */
    383:         for (j=0;j<nd1cols;j++) {
    384:           ncols = md_i[d1cols[j]+1]-md_i[d1cols[j]];
    385:           cidx = &(md_j[md_i[d1cols[j]]]);
    386:           for (l=0;l<ncols;l++) {
    387:             ccol=dcolors[cidx[l]];
    388:             if (ccol != maxcolors) {
    389:               if (ccol>=masksize) {
    390:                 PetscInt *newmask;
    391:                 PetscMalloc1(masksize*2,&newmask);
    392:                 for(k=0;k<2*masksize;k++) {
    393:                   newmask[k]=-1;
    394:                 }
    395:                 for(k=0;k<masksize;k++) {
    396:                   newmask[k]=mask[k];
    397:                 }
    398:                 PetscFree(mask);
    399:                 mask=newmask;
    400:                 masksize*=2;
    401:               }
    402:               mask[ccol]=idx;
    403:             }
    404:           }
    405:         }
    406:         /* off-diagonal distance-two rows */
    407:         if (mo) {
    408:           for (j=0;j<nd1cols;j++) {
    409:             ncols = mo_i[d1cols[j]+1]-mo_i[d1cols[j]];
    410:             cidx = &(mo_j[mo_i[d1cols[j]]]);
    411:             for (l=0;l<ncols;l++) {
    412:               ccol=ocolors[cidx[l]];
    413:               if (ccol != maxcolors) {
    414:                 if (ccol>=masksize) {
    415:                   PetscInt *newmask;
    416:                   PetscMalloc1(masksize*2,&newmask);
    417:                   for(k=0;k<2*masksize;k++) {
    418:                     newmask[k]=-1;
    419:                   }
    420:                   for(k=0;k<masksize;k++) {
    421:                     newmask[k]=mask[k];
    422:                   }
    423:                   PetscFree(mask);
    424:                   mask=newmask;
    425:                   masksize*=2;
    426:                 }
    427:                 mask[ccol]=idx;
    428:               }
    429:             }
    430:           }
    431:         }
    432:         /* assign this one the lowest color possible by seeing if there's a gap in the sequence of sorted neighbor colors */
    433:         pcol=0;
    434:         for (j=0;j<masksize;j++) {
    435:           if (mask[j]!=idx) {
    436:             break;
    437:           }
    438:         }
    439:         pcol=j;
    440:         if (pcol>maxcolors) pcol=maxcolors;
    441:         dcolors[idx]=pcol;
    442:         if (pcol>mcol) mcol=pcol;
    443:       }
    444:     }
    445:     PetscLogEventEnd(Mat_Coloring_Local,mc,0,0,0);
    446:     if (mo) {
    447:       /* transfer neighbor colors */
    448:       PetscSFBcastBegin(sf,MPIU_INT,dcolors,ocolors);
    449:       PetscSFBcastEnd(sf,MPIU_INT,dcolors,ocolors);
    450:       /* find the maximum color assigned locally and allocate a mask */
    451:       MPI_Allreduce(&mcol,&mcol_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)mc));
    452:       PetscMalloc1(mcol_global+1,&colorweights);
    453:       /* check for conflicts */
    454:       for (i=0;i<n;i++) {
    455:         conf[i]=PETSC_FALSE;
    456:       }
    457:       for (i=0;i<no;i++) {
    458:         oconf[i]=PETSC_FALSE;
    459:       }
    460:       for (i=0;i<n;i++) {
    461:         ncols = mo_i[i+1]-mo_i[i];
    462:         cidx = &(mo_j[mo_i[i]]);
    463:         if (ncols > 0) {
    464:           /* fill in the mask */
    465:           for (j=0;j<mcol_global+1;j++) {
    466:             colorweights[j]=0;
    467:           }
    468:           colorweights[dcolors[i]]=wts[i];
    469:           /* fill in the off-diagonal part of the mask */
    470:           for (j=0;j<ncols;j++) {
    471:             ccol=ocolors[cidx[j]];
    472:             if (ccol < maxcolors) {
    473:               if (colorweights[ccol] < owts[cidx[j]]) {
    474:                 colorweights[ccol] = owts[cidx[j]];
    475:               }
    476:             }
    477:           }
    478:           /* fill in the on-diagonal part of the mask */
    479:           ncols = md_i[i+1]-md_i[i];
    480:           cidx = &(md_j[md_i[i]]);
    481:           for (j=0;j<ncols;j++) {
    482:             ccol=dcolors[cidx[j]];
    483:             if (ccol < maxcolors) {
    484:               if (colorweights[ccol] < wts[cidx[j]]) {
    485:                 colorweights[ccol] = wts[cidx[j]];
    486:               }
    487:             }
    488:           }
    489:           /* go back through and set up on and off-diagonal conflict vectors */
    490:           ncols = md_i[i+1]-md_i[i];
    491:           cidx = &(md_j[md_i[i]]);
    492:           for (j=0;j<ncols;j++) {
    493:             ccol=dcolors[cidx[j]];
    494:             if (ccol < maxcolors) {
    495:               if (colorweights[ccol] > wts[cidx[j]]) {
    496:                 conf[cidx[j]]=PETSC_TRUE;
    497:               }
    498:             }
    499:           }
    500:           ncols = mo_i[i+1]-mo_i[i];
    501:           cidx = &(mo_j[mo_i[i]]);
    502:           for (j=0;j<ncols;j++) {
    503:             ccol=ocolors[cidx[j]];
    504:             if (ccol < maxcolors) {
    505:               if (colorweights[ccol] > owts[cidx[j]]) {
    506:                 oconf[cidx[j]]=PETSC_TRUE;
    507:               }
    508:             }
    509:           }
    510:         }
    511:       }
    512:       nd_global=0;
    513:       PetscFree(colorweights);
    514:       PetscLogEventBegin(Mat_Coloring_Comm,mc,0,0,0);
    515:       PetscSFReduceBegin(sf,MPIU_INT,oconf,conf,MPIU_SUM);
    516:       PetscSFReduceEnd(sf,MPIU_INT,oconf,conf,MPIU_SUM);
    517:       PetscLogEventEnd(Mat_Coloring_Comm,mc,0,0,0);
    518:       /* go through and unset local colors that have conflicts */
    519:       for (i=0;i<n;i++) {
    520:         if (conf[i]>0) {
    521:           /* push this color onto the bad stack */
    522:           badidx[nbad]=dcolors[i];
    523:           badnext[nbad]=bad[i];
    524:           bad[i]=nbad;
    525:           nbad++;
    526:           if (nbad>=badsize) {
    527:             PetscInt *newbadnext;
    528:             ISColoringValue *newbadidx;
    529:             PetscMalloc2(badsize*2,&newbadidx,badsize*2,&newbadnext);
    530:             for(k=0;k<2*badsize;k++) {
    531:               newbadnext[k]=-1;
    532:             }
    533:             for(k=0;k<badsize;k++) {
    534:               newbadidx[k]=badidx[k];
    535:               newbadnext[k]=badnext[k];
    536:             }
    537:             PetscFree2(badidx,badnext);
    538:             badidx=newbadidx;
    539:             badnext=newbadnext;
    540:             badsize*=2;
    541:           }
    542:           dcolors[i] = maxcolors;
    543:           nd--;
    544:         }
    545:       }
    546:     }
    547:     MPI_Allreduce(&nd,&nd_global,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)mc));
    548:   }
    549:   if (mo) {
    550:     PetscSFDestroy(&sf);
    551:     PetscFree3(owts,oconf,ocolors);
    552:   }
    553:   for (i=0;i<n;i++) {
    554:     colors[i]=dcolors[i];
    555:   }
    556:   PetscFree(mask);
    557:   PetscFree4(d1cols,dcolors,conf,bad);
    558:   PetscFree2(badidx,badnext);
    559:   if (!gr->symmetric) {MatDestroy(&mt);}
    560:   return(0);
    561: }

    565: PETSC_EXTERN PetscErrorCode MatColoringApply_Greedy(MatColoring mc,ISColoring *iscoloring)
    566: {
    567:   PetscErrorCode  ierr;
    568:   PetscInt        finalcolor,finalcolor_global;
    569:   ISColoringValue *colors;
    570:   PetscInt        ncolstotal,ncols;
    571:   PetscReal       *wts;
    572:   PetscInt        i,*lperm;

    575:   MatGetSize(mc->mat,NULL,&ncolstotal);
    576:   MatGetLocalSize(mc->mat,NULL,&ncols);
    577:   if (!mc->user_weights) {
    578:     MatColoringCreateWeights(mc,&wts,&lperm);
    579:   } else {
    580:     wts = mc->user_weights;
    581:     lperm = mc->user_lperm;
    582:   }
    583:   PetscMalloc1(ncols,&colors);
    584:   if (mc->dist == 1) {
    585:     GreedyColoringLocalDistanceOne_Private(mc,wts,lperm,colors);
    586:   } else if (mc->dist == 2) {
    587:     GreedyColoringLocalDistanceTwo_Private(mc,wts,lperm,colors);
    588:   } else {
    589:     SETERRQ(PetscObjectComm((PetscObject)mc),PETSC_ERR_ARG_OUTOFRANGE,"Only distance 1 and distance 2 supported by MatColoringGreedy");
    590:   }
    591:   finalcolor=0;
    592:   for (i=0;i<ncols;i++) {
    593:     if (colors[i] > finalcolor) finalcolor=colors[i];
    594:   }
    595:   finalcolor_global=0;
    596:   MPI_Allreduce(&finalcolor,&finalcolor_global,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)mc));
    597:   PetscLogEventBegin(Mat_Coloring_ISCreate,mc,0,0,0);
    598:   ISColoringCreate(PetscObjectComm((PetscObject)mc),finalcolor_global+1,ncols,colors,PETSC_OWN_POINTER,iscoloring);
    599:   PetscLogEventEnd(Mat_Coloring_ISCreate,mc,0,0,0);
    600:   if (!mc->user_weights) {
    601:     PetscFree(wts);
    602:     PetscFree(lperm);
    603:   }
    604:   return(0);
    605: }

    609: PetscErrorCode MatColoringSetFromOptions_Greedy(PetscOptions *PetscOptionsObject, MatColoring mc)
    610: {
    611:   MC_Greedy     *gr = (MC_Greedy *) mc->data;

    615:   PetscOptionsHead(PetscOptionsObject, "Greedy options");
    616:   PetscOptionsBool("-mat_coloring_greedy_symmetric", "Flag for assuming a symmetric matrix", "", gr->symmetric, &gr->symmetric, NULL);
    617:   PetscOptionsTail();
    618:   return(0);
    619: }

    623: /*MC
    624:   MATCOLORINGGREEDY - Greedy-with-conflict correction based Matrix Coloring for distance 1 and 2.

    626:    Level: beginner

    628:    Notes:

    630:    These algorithms proceed in two phases -- local coloring and conflict resolution.  The local coloring
    631:    tentatively colors all vertices at the distance required given what's known of the global coloring.  Then,
    632:    the updated colors are transferred to different processors at distance one.  In the distance one case, each
    633:    vertex with nonlocal neighbors is then checked to see if it conforms, with the vertex being
    634:    marked for recoloring if its lower weight than its same colored neighbor.  In the distance two case,
    635:    each boundary vertex's immediate star is checked for validity of the coloring.  Lower-weight conflict
    636:    vertices are marked, and then the conflicts are gathered back on owning processors.  In both cases
    637:    this is done until each column has received a valid color.

    639:    References:

    641:    Bozdag et al. "A Parallel Distance-2 Graph Coloring Algorithm for Distributed Memory Computers"
    642:    HPCC'05 Proceedings of the First international conference on High Performance Computing and Communications
    643:    Pages 796--806

    645: .seealso: MatColoringCreate(), MatColoring, MatColoringSetType()
    646: M*/
    647: PETSC_EXTERN PetscErrorCode MatColoringCreate_Greedy(MatColoring mc)
    648: {
    649:   MC_Greedy      *gr;

    653:   PetscNewLog(mc,&gr);
    654:   mc->data                = gr;
    655:   mc->ops->apply          = MatColoringApply_Greedy;
    656:   mc->ops->view           = NULL;
    657:   mc->ops->destroy        = MatColoringDestroy_Greedy;
    658:   mc->ops->setfromoptions = MatColoringSetFromOptions_Greedy;

    660:   gr->symmetric = PETSC_TRUE;
    661:   return(0);
    662: }