Actual source code: fdmatrix.c

petsc-3.8.4 2018-03-24
Report Typos and Errors

  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: {

 15:   if (F) {
 16:     VecCopy(F,fd->w1);
 17:     fd->fset = PETSC_TRUE;
 18:   } else {
 19:     fd->fset = PETSC_FALSE;
 20:   }
 21:   return(0);
 22: }

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

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

 47: static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
 48: {
 50:   PetscBool      isnull;
 51:   PetscDraw      draw;
 52:   PetscReal      xr,yr,xl,yl,h,w;

 55:   PetscViewerDrawGetDraw(viewer,0,&draw);
 56:   PetscDrawIsNull(draw,&isnull);
 57:   if (isnull) return(0);

 59:   xr   = fd->N; yr  = fd->M; h = yr/10.0; w = xr/10.0;
 60:   xr  += w;     yr += h;    xl = -w;     yl = -h;
 61:   PetscDrawSetCoordinates(draw,xl,yl,xr,yr);
 62:   PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);
 63:   PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);
 64:   PetscObjectCompose((PetscObject)fd,"Zoomviewer",NULL);
 65:   PetscDrawSave(draw);
 66:   return(0);
 67: }

 69: /*@C
 70:    MatFDColoringView - Views a finite difference coloring context.

 72:    Collective on MatFDColoring

 74:    Input  Parameters:
 75: +  c - the coloring context
 76: -  viewer - visualization context

 78:    Level: intermediate

 80:    Notes:
 81:    The available visualization contexts include
 82: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
 83: .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
 84:         output where only the first processor opens
 85:         the file.  All other processors send their
 86:         data to the first processor to print.
 87: -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure

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

 94: .seealso: MatFDColoringCreate()

 96: .keywords: Mat, finite differences, coloring, view
 97: @*/
 98: PetscErrorCode  MatFDColoringView(MatFDColoring c,PetscViewer viewer)
 99: {
100:   PetscErrorCode    ierr;
101:   PetscInt          i,j;
102:   PetscBool         isdraw,iascii;
103:   PetscViewerFormat format;

107:   if (!viewer) {
108:     PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer);
109:   }

113:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
114:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
115:   if (isdraw) {
116:     MatFDColoringView_Draw(c,viewer);
117:   } else if (iascii) {
118:     PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer);
119:     PetscViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",(double)c->error_rel);
120:     PetscViewerASCIIPrintf(viewer,"  Umin=%g\n",(double)c->umin);
121:     PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);

123:     PetscViewerGetFormat(viewer,&format);
124:     if (format != PETSC_VIEWER_ASCII_INFO) {
125:       PetscInt row,col,nz;
126:       nz = 0;
127:       for (i=0; i<c->ncolors; i++) {
128:         PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);
129:         PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);
130:         for (j=0; j<c->ncolumns[i]; j++) {
131:           PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);
132:         }
133:         PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);
134:         if (c->matentry) {
135:           for (j=0; j<c->nrows[i]; j++) {
136:             row  = c->matentry[nz].row;
137:             col  = c->matentry[nz++].col;
138:             PetscViewerASCIIPrintf(viewer,"      %D %D \n",row,col);
139:           }
140:         }
141:       }
142:     }
143:     PetscViewerFlush(viewer);
144:   }
145:   return(0);
146: }

148: /*@
149:    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
150:    a Jacobian matrix using finite differences.

152:    Logically Collective on MatFDColoring

154:    The Jacobian is estimated with the differencing approximation
155: .vb
156:        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
157:        h = error_rel*u[i]                 if  abs(u[i]) > umin
158:          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
159:        dx_{i} = (0, ... 1, .... 0)
160: .ve

162:    Input Parameters:
163: +  coloring - the coloring context
164: .  error_rel - relative error
165: -  umin - minimum allowable u-value magnitude

167:    Level: advanced

169: .keywords: Mat, finite differences, coloring, set, parameters

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

173: @*/
174: PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
175: {
180:   if (error != PETSC_DEFAULT) matfd->error_rel = error;
181:   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
182:   return(0);
183: }

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

188:    Logically Collective on MatFDColoring

190:    Input Parameters:
191: +  coloring - the coloring context
192: .  brows - number of rows in the block
193: -  bcols - number of columns in the block

195:    Level: intermediate

197: .keywords: Mat, coloring

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

201: @*/
202: PetscErrorCode MatFDColoringSetBlockSize(MatFDColoring matfd,PetscInt brows,PetscInt bcols)
203: {
208:   if (brows != PETSC_DEFAULT) matfd->brows = brows;
209:   if (bcols != PETSC_DEFAULT) matfd->bcols = bcols;
210:   return(0);
211: }

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

216:    Collective on Mat

218:    Input Parameters:
219: +  mat - the matrix containing the nonzero structure of the Jacobian
220: .  iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMCreateColoring()
221: -  color - the matrix coloring context

223:    Level: beginner

225: .keywords: MatFDColoring, setup

227: .seealso: MatFDColoringCreate(), MatFDColoringDestroy()
228: @*/
229: PetscErrorCode MatFDColoringSetUp(Mat mat,ISColoring iscoloring,MatFDColoring color)
230: {

236:   if (color->setupcalled) return(0);

238:   PetscLogEventBegin(MAT_FDColoringSetUp,mat,0,0,0);
239:   if (mat->ops->fdcoloringsetup) {
240:     (*mat->ops->fdcoloringsetup)(mat,iscoloring,color);
241:   } else SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);

243:   color->setupcalled = PETSC_TRUE;
244:    PetscLogEventEnd(MAT_FDColoringSetUp,mat,0,0,0);
245:   return(0);
246: }

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

251:    Not Collective

253:    Input Parameters:
254: .  coloring - the coloring context

256:    Output Parameters:
257: +  f - the function
258: -  fctx - the optional user-defined function context

260:    Level: intermediate

262: .keywords: Mat, Jacobian, finite differences, set, function

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

266: @*/
267: PetscErrorCode  MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
268: {
271:   if (f) *f = matfd->f;
272:   if (fctx) *fctx = matfd->fctx;
273:   return(0);
274: }

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

279:    Logically Collective on MatFDColoring

281:    Input Parameters:
282: +  coloring - the coloring context
283: .  f - the function
284: -  fctx - the optional user-defined function context

286:    Calling sequence of (*f) function:
287:     For SNES:    PetscErrorCode (*f)(SNES,Vec,Vec,void*)
288:     If not using SNES: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored

290:    Level: advanced

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

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

300: .keywords: Mat, Jacobian, finite differences, set, function

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

304: @*/
305: PetscErrorCode  MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
306: {
309:   matfd->f    = f;
310:   matfd->fctx = fctx;
311:   return(0);
312: }

314: /*@
315:    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
316:    the options database.

318:    Collective on MatFDColoring

320:    The Jacobian, F'(u), is estimated with the differencing approximation
321: .vb
322:        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
323:        h = error_rel*u[i]                 if  abs(u[i]) > umin
324:          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
325:        dx_{i} = (0, ... 1, .... 0)
326: .ve

328:    Input Parameter:
329: .  coloring - the coloring context

331:    Options Database Keys:
332: +  -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function)
333: .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
334: .  -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
335: .  -mat_fd_coloring_view - Activates basic viewing
336: .  -mat_fd_coloring_view ::ascii_info - Activates viewing info
337: -  -mat_fd_coloring_view draw - Activates drawing

339:     Level: intermediate

341: .keywords: Mat, finite differences, parameters

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

345: @*/
346: PetscErrorCode  MatFDColoringSetFromOptions(MatFDColoring matfd)
347: {
349:   PetscBool      flg;
350:   char           value[3];


355:   PetscObjectOptionsBegin((PetscObject)matfd);
356:   PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);
357:   PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);
358:   PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,3,&flg);
359:   if (flg) {
360:     if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
361:     else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
362:     else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
363:   }
364:   PetscOptionsInt("-mat_fd_coloring_brows","Number of block rows","MatFDColoringSetBlockSize",matfd->brows,&matfd->brows,NULL);
365:   PetscOptionsInt("-mat_fd_coloring_bcols","Number of block columns","MatFDColoringSetBlockSize",matfd->bcols,&matfd->bcols,&flg);
366:   if (flg && matfd->bcols > matfd->ncolors) {
367:     /* input bcols cannot be > matfd->ncolors, thus set it as ncolors */
368:     matfd->bcols = matfd->ncolors;
369:   }

371:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
372:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)matfd);
373:   PetscOptionsEnd();
374:   return(0);
375: }

377: /*@C
378:    MatFDColoringSetType - Sets the approach for computing the finite difference parameter

380:    Collective on MatFDColoring

382:    Input Parameters:
383: +  coloring - the coloring context
384: -  type - either MATMFFD_WP or MATMFFD_DS

386:    Options Database Keys:
387: .  -mat_fd_type - "wp" or "ds"

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

393:    Level: intermediate

395: .keywords: Mat, finite differences, parameters

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

399: @*/
400: PetscErrorCode  MatFDColoringSetType(MatFDColoring matfd,MatMFFDType type)
401: {
404:   /*
405:      It is goofy to handle the strings this way but currently there is no code to free a dynamically created matfd->htype
406:      and this function is being provided as patch for a release so it shouldn't change the implementaton
407:   */
408:   if (type[0] == 'w' && type[1] == 'p') matfd->htype = "wp";
409:   else if (type[0] == 'd' && type[1] == 's') matfd->htype = "ds";
410:   else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",type);
411:   return(0);
412: }

414: PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd,const char prefix[],const char optionname[])
415: {
416:   PetscErrorCode    ierr;
417:   PetscBool         flg;
418:   PetscViewer       viewer;
419:   PetscViewerFormat format;

422:   if (prefix) {
423:     PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),prefix,optionname,&viewer,&format,&flg);
424:   } else {
425:     PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),((PetscObject)fd)->prefix,optionname,&viewer,&format,&flg);
426:   }
427:   if (flg) {
428:     PetscViewerPushFormat(viewer,format);
429:     MatFDColoringView(fd,viewer);
430:     PetscViewerPopFormat(viewer);
431:     PetscViewerDestroy(&viewer);
432:   }
433:   return(0);
434: }

436: /*@
437:    MatFDColoringCreate - Creates a matrix coloring context for finite difference
438:    computation of Jacobians.

440:    Collective on Mat

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

446:     Output Parameter:
447: .   color - the new coloring context

449:     Level: intermediate

451: .seealso: MatFDColoringDestroy(),SNESComputeJacobianDefaultColor(), ISColoringCreate(),
452:           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
453:           MatFDColoringView(), MatFDColoringSetParameters(), MatColoringCreate(), DMCreateColoring()
454: @*/
455: PetscErrorCode  MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
456: {
457:   MatFDColoring  c;
458:   MPI_Comm       comm;
460:   PetscInt       M,N;

464:   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
465:   PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);
466:   MatGetSize(mat,&M,&N);
467:   if (M != N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Only for square matrices");
468:   PetscObjectGetComm((PetscObject)mat,&comm);
469:   PetscHeaderCreate(c,MAT_FDCOLORING_CLASSID,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);

471:   c->ctype = iscoloring->ctype;

473:   if (mat->ops->fdcoloringcreate) {
474:     (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);
475:   } else SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);

477:   MatCreateVecs(mat,NULL,&c->w1);
478:   PetscLogObjectParent((PetscObject)c,(PetscObject)c->w1);
479:   VecDuplicate(c->w1,&c->w2);
480:   PetscLogObjectParent((PetscObject)c,(PetscObject)c->w2);

482:   c->error_rel    = PETSC_SQRT_MACHINE_EPSILON;
483:   c->umin         = 100.0*PETSC_SQRT_MACHINE_EPSILON;
484:   c->currentcolor = -1;
485:   c->htype        = "wp";
486:   c->fset         = PETSC_FALSE;
487:   c->setupcalled  = PETSC_FALSE;

489:   *color = c;
490:   PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);
491:   PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);
492:   return(0);
493: }

495: /*@
496:     MatFDColoringDestroy - Destroys a matrix coloring context that was created
497:     via MatFDColoringCreate().

499:     Collective on MatFDColoring

501:     Input Parameter:
502: .   c - coloring context

504:     Level: intermediate

506: .seealso: MatFDColoringCreate()
507: @*/
508: PetscErrorCode  MatFDColoringDestroy(MatFDColoring *c)
509: {
511:   PetscInt       i;
512:   MatFDColoring  color = *c;

515:   if (!*c) return(0);
516:   if (--((PetscObject)color)->refct > 0) {*c = 0; return(0);}

518:   for (i=0; i<color->ncolors; i++) {
519:     PetscFree(color->columns[i]);
520:   }
521:   PetscFree(color->ncolumns);
522:   PetscFree(color->columns);
523:   PetscFree(color->nrows);
524:   if (color->htype[0] == 'w') {
525:     PetscFree(color->matentry2);
526:   } else {
527:     PetscFree(color->matentry);
528:   }
529:   PetscFree(color->dy);
530:   if (color->vscale) {VecDestroy(&color->vscale);}
531:   VecDestroy(&color->w1);
532:   VecDestroy(&color->w2);
533:   VecDestroy(&color->w3);
534:   PetscHeaderDestroy(c);
535:   return(0);
536: }

538: /*@C
539:     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
540:       that are currently being perturbed.

542:     Not Collective

544:     Input Parameters:
545: .   coloring - coloring context created with MatFDColoringCreate()

547:     Output Parameters:
548: +   n - the number of local columns being perturbed
549: -   cols - the column indices, in global numbering

551:    Level: intermediate

553:    Fortran Note:
554:    This routine has a different interface for Fortran
555: $          use petscisdef
556: $          PetscInt, pointer :: array(:)
557: $          PetscErrorCode  ierr
558: $          MatFDColoring   i
559: $          call MatFDColoringGetPerturbedColumnsF90(i,array,ierr)
560: $      use the entries of array ...
561: $          call MatFDColoringRestorePerturbedColumnsF90(i,array,ierr)

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

565: .keywords: coloring, Jacobian, finite differences
566: @*/
567: PetscErrorCode  MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,const PetscInt *cols[])
568: {
570:   if (coloring->currentcolor >= 0) {
571:     *n    = coloring->ncolumns[coloring->currentcolor];
572:     *cols = coloring->columns[coloring->currentcolor];
573:   } else {
574:     *n = 0;
575:   }
576:   return(0);
577: }

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

583:     Collective on MatFDColoring

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

591:     Options Database Keys:
592: +    -mat_fd_type - "wp" or "ds"  (see MATMFFD_WP or MATMFFD_DS)
593: .    -mat_fd_coloring_view - Activates basic viewing or coloring
594: .    -mat_fd_coloring_view draw - Activates drawing of coloring
595: -    -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info

597:     Level: intermediate

599: .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction()

601: .keywords: coloring, Jacobian, finite differences
602: @*/
603: PetscErrorCode  MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
604: {
606:   PetscBool      flg = PETSC_FALSE;

612:   if (!coloring->f) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
613:   if (!J->ops->fdcoloringapply) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)J)->type_name);
614:   if (!coloring->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetUp()");

616:   MatSetUnfactored(J);
617:   PetscOptionsGetBool(((PetscObject)coloring)->options,NULL,"-mat_fd_coloring_dont_rezero",&flg,NULL);
618:   if (flg) {
619:     PetscInfo(coloring,"Not calling MatZeroEntries()\n");
620:   } else {
621:     PetscBool assembled;
622:     MatAssembled(J,&assembled);
623:     if (assembled) {
624:       MatZeroEntries(J);
625:     }
626:   }

628:   PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);
629:   (*J->ops->fdcoloringapply)(J,coloring,x1,sctx);
630:   PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);
631:   if (!coloring->viewed) {
632:     MatFDColoringViewFromOptions(coloring,NULL,"-mat_fd_coloring_view");
633:     coloring->viewed = PETSC_TRUE;
634:   }
635:   return(0);
636: }