Actual source code: fdmatrix.c

      2: /*
      3:    This is where the abstract matrix operations are defined that are
      4:   used for finite difference computations of Jacobians using coloring.
      5: */

      7: #include <petsc/private/matimpl.h>
      8: #include <petsc/private/isimpl.h>

     10: PetscErrorCode  MatFDColoringSetF(MatFDColoring fd,Vec F)
     11: {
     12:   if (F) {
     13:     VecCopy(F,fd->w1);
     14:     fd->fset = PETSC_TRUE;
     15:   } else {
     16:     fd->fset = PETSC_FALSE;
     17:   }
     18:   return 0;
     19: }

     21: #include <petscdraw.h>
     22: static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
     23: {
     24:   MatFDColoring  fd = (MatFDColoring)Aa;
     25:   PetscInt       i,j,nz,row;
     26:   PetscReal      x,y;
     27:   MatEntry       *Jentry=fd->matentry;

     29:   /* loop over colors  */
     30:   nz = 0;
     31:   for (i=0; i<fd->ncolors; i++) {
     32:     for (j=0; j<fd->nrows[i]; j++) {
     33:       row = Jentry[nz].row;
     34:       y   = fd->M - row - fd->rstart;
     35:       x   = (PetscReal)Jentry[nz++].col;
     36:       PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);
     37:     }
     38:   }
     39:   return 0;
     40: }

     42: static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
     43: {
     44:   PetscBool      isnull;
     45:   PetscDraw      draw;
     46:   PetscReal      xr,yr,xl,yl,h,w;

     48:   PetscViewerDrawGetDraw(viewer,0,&draw);
     49:   PetscDrawIsNull(draw,&isnull);
     50:   if (isnull) return 0;

     52:   xr   = fd->N; yr  = fd->M; h = yr/10.0; w = xr/10.0;
     53:   xr  += w;     yr += h;    xl = -w;     yl = -h;
     54:   PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
     55:   PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);
     56:   PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);
     57:   PetscObjectCompose((PetscObject)fd,"Zoomviewer",NULL);
     58:   PetscDrawSave(draw);
     59:   return 0;
     60: }

     62: /*@C
     63:    MatFDColoringView - Views a finite difference coloring context.

     65:    Collective on MatFDColoring

     67:    Input  Parameters:
     68: +  c - the coloring context
     69: -  viewer - visualization context

     71:    Level: intermediate

     73:    Notes:
     74:    The available visualization contexts include
     75: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
     76: .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
     77:         output where only the first processor opens
     78:         the file.  All other processors send their
     79:         data to the first processor to print.
     80: -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure

     82:    Notes:
     83:      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
     84:    involves more than 33 then some seemingly identical colors are displayed making it look
     85:    like an illegal coloring. This is just a graphical artifact.

     87: .seealso: MatFDColoringCreate()

     89: @*/
     90: PetscErrorCode  MatFDColoringView(MatFDColoring c,PetscViewer viewer)
     91: {
     92:   PetscInt          i,j;
     93:   PetscBool         isdraw,iascii;
     94:   PetscViewerFormat format;

     97:   if (!viewer) {
     98:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer);
     99:   }

    103:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
    104:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    105:   if (isdraw) {
    106:     MatFDColoringView_Draw(c,viewer);
    107:   } else if (iascii) {
    108:     PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer);
    109:     PetscViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",(double)c->error_rel);
    110:     PetscViewerASCIIPrintf(viewer,"  Umin=%g\n",(double)c->umin);
    111:     PetscViewerASCIIPrintf(viewer,"  Number of colors=%" PetscInt_FMT "\n",c->ncolors);

    113:     PetscViewerGetFormat(viewer,&format);
    114:     if (format != PETSC_VIEWER_ASCII_INFO) {
    115:       PetscInt row,col,nz;
    116:       nz = 0;
    117:       for (i=0; i<c->ncolors; i++) {
    118:         PetscViewerASCIIPrintf(viewer,"  Information for color %" PetscInt_FMT "\n",i);
    119:         PetscViewerASCIIPrintf(viewer,"    Number of columns %" PetscInt_FMT "\n",c->ncolumns[i]);
    120:         for (j=0; j<c->ncolumns[i]; j++) {
    121:           PetscViewerASCIIPrintf(viewer,"      %" PetscInt_FMT "\n",c->columns[i][j]);
    122:         }
    123:         PetscViewerASCIIPrintf(viewer,"    Number of rows %" PetscInt_FMT "\n",c->nrows[i]);
    124:         if (c->matentry) {
    125:           for (j=0; j<c->nrows[i]; j++) {
    126:             row  = c->matentry[nz].row;
    127:             col  = c->matentry[nz++].col;
    128:             PetscViewerASCIIPrintf(viewer,"      %" PetscInt_FMT " %" PetscInt_FMT " \n",row,col);
    129:           }
    130:         }
    131:       }
    132:     }
    133:     PetscViewerFlush(viewer);
    134:   }
    135:   return 0;
    136: }

    138: /*@
    139:    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
    140:    a Jacobian matrix using finite differences.

    142:    Logically Collective on MatFDColoring

    144:    The Jacobian is estimated with the differencing approximation
    145: .vb
    146:        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
    147:        htype = 'ds':
    148:          h = error_rel*u[i]                 if  abs(u[i]) > umin
    149:            = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
    150:          dx_{i} = (0, ... 1, .... 0)

    152:        htype = 'wp':
    153:          h = error_rel * sqrt(1 + ||u||)
    154: .ve

    156:    Input Parameters:
    157: +  coloring - the coloring context
    158: .  error_rel - relative error
    159: -  umin - minimum allowable u-value magnitude

    161:    Level: advanced

    163: .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()

    165: @*/
    166: PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
    167: {
    171:   if (error != PETSC_DEFAULT) matfd->error_rel = error;
    172:   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
    173:   return 0;
    174: }

    176: /*@
    177:    MatFDColoringSetBlockSize - Sets block size for efficient inserting entries of Jacobian matrix.

    179:    Logically Collective on MatFDColoring

    181:    Input Parameters:
    182: +  coloring - the coloring context
    183: .  brows - number of rows in the block
    184: -  bcols - number of columns in the block

    186:    Level: intermediate

    188: .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()

    190: @*/
    191: PetscErrorCode MatFDColoringSetBlockSize(MatFDColoring matfd,PetscInt brows,PetscInt bcols)
    192: {
    196:   if (brows != PETSC_DEFAULT) matfd->brows = brows;
    197:   if (bcols != PETSC_DEFAULT) matfd->bcols = bcols;
    198:   return 0;
    199: }

    201: /*@
    202:    MatFDColoringSetUp - Sets up the internal data structures of matrix coloring context for the later use.

    204:    Collective on Mat

    206:    Input Parameters:
    207: +  mat - the matrix containing the nonzero structure of the Jacobian
    208: .  iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMCreateColoring()
    209: -  color - the matrix coloring context

    211:    Level: beginner

    213:    Notes: When the coloring type is IS_COLORING_LOCAL the coloring is in the local ordering of the unknowns.

    215: .seealso: MatFDColoringCreate(), MatFDColoringDestroy()
    216: @*/
    217: PetscErrorCode MatFDColoringSetUp(Mat mat,ISColoring iscoloring,MatFDColoring color)
    218: {
    219:   PetscBool      eq;

    223:   if (color->setupcalled) return 0;
    224:   PetscObjectCompareId((PetscObject)mat,color->matid,&eq);

    227:   PetscLogEventBegin(MAT_FDColoringSetUp,mat,0,0,0);
    228:   if (mat->ops->fdcoloringsetup) {
    229:     (*mat->ops->fdcoloringsetup)(mat,iscoloring,color);
    230:   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);

    232:   color->setupcalled = PETSC_TRUE;
    233:    PetscLogEventEnd(MAT_FDColoringSetUp,mat,0,0,0);
    234:   return 0;
    235: }

    237: /*@C
    238:    MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.

    240:    Not Collective

    242:    Input Parameter:
    243: .  coloring - the coloring context

    245:    Output Parameters:
    246: +  f - the function
    247: -  fctx - the optional user-defined function context

    249:    Level: intermediate

    251: .seealso: MatFDColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions()

    253: @*/
    254: PetscErrorCode  MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
    255: {
    257:   if (f) *f = matfd->f;
    258:   if (fctx) *fctx = matfd->fctx;
    259:   return 0;
    260: }

    262: /*@C
    263:    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.

    265:    Logically Collective on MatFDColoring

    267:    Input Parameters:
    268: +  coloring - the coloring context
    269: .  f - the function
    270: -  fctx - the optional user-defined function context

    272:    Calling sequence of (*f) function:
    273:     For SNES:    PetscErrorCode (*f)(SNES,Vec,Vec,void*)
    274:     If not using SNES: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored

    276:    Level: advanced

    278:    Notes:
    279:     This function is usually used automatically by SNES (when one uses SNESSetJacobian() with the argument
    280:      SNESComputeJacobianDefaultColor()) and only needs to be used by someone computing a matrix via coloring directly by
    281:      calling MatFDColoringApply()

    283:    Fortran Notes:
    284:     In Fortran you must call MatFDColoringSetFunction() for a coloring object to
    285:   be used without SNES or within the SNES solvers.

    287: .seealso: MatFDColoringCreate(), MatFDColoringGetFunction(), MatFDColoringSetFromOptions()

    289: @*/
    290: PetscErrorCode  MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
    291: {
    293:   matfd->f    = f;
    294:   matfd->fctx = fctx;
    295:   return 0;
    296: }

    298: /*@
    299:    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
    300:    the options database.

    302:    Collective on MatFDColoring

    304:    The Jacobian, F'(u), is estimated with the differencing approximation
    305: .vb
    306:        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
    307:        h = error_rel*u[i]                 if  abs(u[i]) > umin
    308:          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
    309:        dx_{i} = (0, ... 1, .... 0)
    310: .ve

    312:    Input Parameter:
    313: .  coloring - the coloring context

    315:    Options Database Keys:
    316: +  -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function)
    317: .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
    318: .  -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
    319: .  -mat_fd_coloring_view - Activates basic viewing
    320: .  -mat_fd_coloring_view ::ascii_info - Activates viewing info
    321: -  -mat_fd_coloring_view draw - Activates drawing

    323:     Level: intermediate

    325: .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()

    327: @*/
    328: PetscErrorCode  MatFDColoringSetFromOptions(MatFDColoring matfd)
    329: {
    331:   PetscBool      flg;
    332:   char           value[3];

    336:   PetscObjectOptionsBegin((PetscObject)matfd);
    337:   PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,NULL);
    338:   PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,NULL);
    339:   PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,sizeof(value),&flg);
    340:   if (flg) {
    341:     if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
    342:     else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
    343:     else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
    344:   }
    345:   PetscOptionsInt("-mat_fd_coloring_brows","Number of block rows","MatFDColoringSetBlockSize",matfd->brows,&matfd->brows,NULL);
    346:   PetscOptionsInt("-mat_fd_coloring_bcols","Number of block columns","MatFDColoringSetBlockSize",matfd->bcols,&matfd->bcols,&flg);
    347:   if (flg && matfd->bcols > matfd->ncolors) {
    348:     /* input bcols cannot be > matfd->ncolors, thus set it as ncolors */
    349:     matfd->bcols = matfd->ncolors;
    350:   }

    352:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
    353:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)matfd);
    354:   PetscOptionsEnd();
    355:   return 0;
    356: }

    358: /*@C
    359:    MatFDColoringSetType - Sets the approach for computing the finite difference parameter

    361:    Collective on MatFDColoring

    363:    Input Parameters:
    364: +  coloring - the coloring context
    365: -  type - either MATMFFD_WP or MATMFFD_DS

    367:    Options Database Keys:
    368: .  -mat_fd_type - "wp" or "ds"

    370:    Note: It is goofy that the argument type is MatMFFDType since the MatFDColoring actually computes the matrix entries
    371:          but the process of computing the entries is the same as as with the MatMFFD operation so we should reuse the names instead of
    372:          introducing another one.

    374:    Level: intermediate

    376: .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()

    378: @*/
    379: PetscErrorCode  MatFDColoringSetType(MatFDColoring matfd,MatMFFDType type)
    380: {
    382:   /*
    383:      It is goofy to handle the strings this way but currently there is no code to free a dynamically created matfd->htype
    384:      and this function is being provided as patch for a release so it shouldn't change the implementaton
    385:   */
    386:   if (type[0] == 'w' && type[1] == 'p') matfd->htype = "wp";
    387:   else if (type[0] == 'd' && type[1] == 's') matfd->htype = "ds";
    388:   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",type);
    389:   return 0;
    390: }

    392: PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd,const char prefix[],const char optionname[])
    393: {
    394:   PetscBool         flg;
    395:   PetscViewer       viewer;
    396:   PetscViewerFormat format;

    398:   if (prefix) {
    399:     PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),((PetscObject)fd)->options,prefix,optionname,&viewer,&format,&flg);
    400:   } else {
    401:     PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),((PetscObject)fd)->options,((PetscObject)fd)->prefix,optionname,&viewer,&format,&flg);
    402:   }
    403:   if (flg) {
    404:     PetscViewerPushFormat(viewer,format);
    405:     MatFDColoringView(fd,viewer);
    406:     PetscViewerPopFormat(viewer);
    407:     PetscViewerDestroy(&viewer);
    408:   }
    409:   return 0;
    410: }

    412: /*@
    413:    MatFDColoringCreate - Creates a matrix coloring context for finite difference
    414:    computation of Jacobians.

    416:    Collective on Mat

    418:    Input Parameters:
    419: +  mat - the matrix containing the nonzero structure of the Jacobian
    420: -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()

    422:     Output Parameter:
    423: .   color - the new coloring context

    425:     Level: intermediate

    427: .seealso: MatFDColoringDestroy(),SNESComputeJacobianDefaultColor(), ISColoringCreate(),
    428:           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
    429:           MatFDColoringView(), MatFDColoringSetParameters(), MatColoringCreate(), DMCreateColoring(), MatFDColoringSetValues()
    430: @*/
    431: PetscErrorCode  MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
    432: {
    433:   MatFDColoring  c;
    434:   MPI_Comm       comm;
    435:   PetscInt       M,N;

    439:   PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);
    440:   MatGetSize(mat,&M,&N);
    442:   PetscObjectGetComm((PetscObject)mat,&comm);
    443:   PetscHeaderCreate(c,MAT_FDCOLORING_CLASSID,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);

    445:   c->ctype = iscoloring->ctype;
    446:   PetscObjectGetId((PetscObject)mat,&c->matid);

    448:   if (mat->ops->fdcoloringcreate) {
    449:     (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);
    450:   } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);

    452:   MatCreateVecs(mat,NULL,&c->w1);
    453:   /* Vec is used intensively in particular piece of scalar CPU code; won't benefit from bouncing back and forth to the GPU */
    454:   VecBindToCPU(c->w1,PETSC_TRUE);
    455:   PetscLogObjectParent((PetscObject)c,(PetscObject)c->w1);
    456:   VecDuplicate(c->w1,&c->w2);
    457:   /* Vec is used intensively in particular piece of scalar CPU code; won't benefit from bouncing back and forth to the GPU */
    458:   VecBindToCPU(c->w2,PETSC_TRUE);
    459:   PetscLogObjectParent((PetscObject)c,(PetscObject)c->w2);

    461:   c->error_rel    = PETSC_SQRT_MACHINE_EPSILON;
    462:   c->umin         = 100.0*PETSC_SQRT_MACHINE_EPSILON;
    463:   c->currentcolor = -1;
    464:   c->htype        = "wp";
    465:   c->fset         = PETSC_FALSE;
    466:   c->setupcalled  = PETSC_FALSE;

    468:   *color = c;
    469:   PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);
    470:   PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);
    471:   return 0;
    472: }

    474: /*@
    475:     MatFDColoringDestroy - Destroys a matrix coloring context that was created
    476:     via MatFDColoringCreate().

    478:     Collective on MatFDColoring

    480:     Input Parameter:
    481: .   c - coloring context

    483:     Level: intermediate

    485: .seealso: MatFDColoringCreate()
    486: @*/
    487: PetscErrorCode  MatFDColoringDestroy(MatFDColoring *c)
    488: {
    489:   PetscInt       i;
    490:   MatFDColoring  color = *c;

    492:   if (!*c) return 0;
    493:   if (--((PetscObject)color)->refct > 0) {*c = NULL; return 0;}

    495:   /* we do not free the column arrays since their entries are owned by the ISs in color->isa */
    496:   for (i=0; i<color->ncolors; i++) {
    497:     ISDestroy(&color->isa[i]);
    498:   }
    499:   PetscFree(color->isa);
    500:   PetscFree2(color->ncolumns,color->columns);
    501:   PetscFree(color->nrows);
    502:   if (color->htype[0] == 'w') {
    503:     PetscFree(color->matentry2);
    504:   } else {
    505:     PetscFree(color->matentry);
    506:   }
    507:   PetscFree(color->dy);
    508:   if (color->vscale) VecDestroy(&color->vscale);
    509:   VecDestroy(&color->w1);
    510:   VecDestroy(&color->w2);
    511:   VecDestroy(&color->w3);
    512:   PetscHeaderDestroy(c);
    513:   return 0;
    514: }

    516: /*@C
    517:     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
    518:       that are currently being perturbed.

    520:     Not Collective

    522:     Input Parameter:
    523: .   coloring - coloring context created with MatFDColoringCreate()

    525:     Output Parameters:
    526: +   n - the number of local columns being perturbed
    527: -   cols - the column indices, in global numbering

    529:    Level: advanced

    531:    Note: IF the matrix type is BAIJ, then the block column indices are returned

    533:    Fortran Note:
    534:    This routine has a different interface for Fortran
    535: #include <petsc/finclude/petscmat.h>
    536: $          use petscmat
    537: $          PetscInt, pointer :: array(:)
    538: $          PetscErrorCode  ierr
    539: $          MatFDColoring   i
    540: $          call MatFDColoringGetPerturbedColumnsF90(i,array,ierr)
    541: $      use the entries of array ...
    542: $          call MatFDColoringRestorePerturbedColumnsF90(i,array,ierr)

    544: .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()

    546: @*/
    547: PetscErrorCode  MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,const PetscInt *cols[])
    548: {
    549:   if (coloring->currentcolor >= 0) {
    550:     *n    = coloring->ncolumns[coloring->currentcolor];
    551:     *cols = coloring->columns[coloring->currentcolor];
    552:   } else {
    553:     *n = 0;
    554:   }
    555:   return 0;
    556: }

    558: /*@
    559:     MatFDColoringApply - Given a matrix for which a MatFDColoring context
    560:     has been created, computes the Jacobian for a function via finite differences.

    562:     Collective on MatFDColoring

    564:     Input Parameters:
    565: +   mat - location to store Jacobian
    566: .   coloring - coloring context created with MatFDColoringCreate()
    567: .   x1 - location at which Jacobian is to be computed
    568: -   sctx - context required by function, if this is being used with the SNES solver then it is SNES object, otherwise it is null

    570:     Options Database Keys:
    571: +    -mat_fd_type - "wp" or "ds"  (see MATMFFD_WP or MATMFFD_DS)
    572: .    -mat_fd_coloring_view - Activates basic viewing or coloring
    573: .    -mat_fd_coloring_view draw - Activates drawing of coloring
    574: -    -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info

    576:     Level: intermediate

    578: .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction(), MatFDColoringSetValues()

    580: @*/
    581: PetscErrorCode  MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
    582: {
    583:   PetscBool      eq;

    588:   PetscObjectCompareId((PetscObject)J,coloring->matid,&eq);

    594:   MatSetUnfactored(J);
    595:   PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);
    596:   (*J->ops->fdcoloringapply)(J,coloring,x1,sctx);
    597:   PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);
    598:   if (!coloring->viewed) {
    599:     MatFDColoringViewFromOptions(coloring,NULL,"-mat_fd_coloring_view");
    600:     coloring->viewed = PETSC_TRUE;
    601:   }
    602:   return 0;
    603: }