xref: /petsc/src/mat/matfd/fdmatrix.c (revision 625f6d37088ae665b5f7ef877d9e50ad1b233616)
1 
2 /*
3    This is where the abstract matrix operations are defined that are
4   used for finite difference computations of Jacobians using coloring.
5 */
6 
7 #include <petsc-private/matimpl.h>        /*I "petscmat.h" I*/
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "MatFDColoringSetF"
11 PetscErrorCode  MatFDColoringSetF(MatFDColoring fd,Vec F)
12 {
13   PetscErrorCode ierr;
14 
15   PetscFunctionBegin;
16   if (F) {
17     ierr     = VecCopy(F,fd->w1);CHKERRQ(ierr);
18     fd->fset = PETSC_TRUE;
19   } else {
20     fd->fset = PETSC_FALSE;
21   }
22   PetscFunctionReturn(0);
23 }
24 
25 #include <petscdraw.h>
26 #undef __FUNCT__
27 #define __FUNCT__ "MatFDColoringView_Draw_Zoom"
28 static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
29 {
30   MatFDColoring  fd = (MatFDColoring)Aa;
31   PetscErrorCode ierr;
32   PetscInt       i,j,nz,row;
33   PetscReal      x,y;
34   MatEntry       *Jentry=fd->matentry;
35 
36   PetscFunctionBegin;
37   /* loop over colors  */
38   nz = 0;
39   for (i=0; i<fd->ncolors; i++) {
40     for (j=0; j<fd->nrows[i]; j++) {
41       row = Jentry[nz].row;
42       y   = fd->M - row - fd->rstart;
43       x   = (PetscReal)Jentry[nz++].col;
44       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
45     }
46   }
47   PetscFunctionReturn(0);
48 }
49 
50 #undef __FUNCT__
51 #define __FUNCT__ "MatFDColoringView_Draw"
52 static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
53 {
54   PetscErrorCode ierr;
55   PetscBool      isnull;
56   PetscDraw      draw;
57   PetscReal      xr,yr,xl,yl,h,w;
58 
59   PetscFunctionBegin;
60   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
61   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
62 
63   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
64 
65   xr   = fd->N; yr  = fd->M; h = yr/10.0; w = xr/10.0;
66   xr  += w;     yr += h;    xl = -w;     yl = -h;
67   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
68   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
69   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",NULL);CHKERRQ(ierr);
70   PetscFunctionReturn(0);
71 }
72 
73 #undef __FUNCT__
74 #define __FUNCT__ "MatFDColoringView"
75 /*@C
76    MatFDColoringView - Views a finite difference coloring context.
77 
78    Collective on MatFDColoring
79 
80    Input  Parameters:
81 +  c - the coloring context
82 -  viewer - visualization context
83 
84    Level: intermediate
85 
86    Notes:
87    The available visualization contexts include
88 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
89 .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
90         output where only the first processor opens
91         the file.  All other processors send their
92         data to the first processor to print.
93 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
94 
95    Notes:
96      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
97    involves more than 33 then some seemingly identical colors are displayed making it look
98    like an illegal coloring. This is just a graphical artifact.
99 
100 .seealso: MatFDColoringCreate()
101 
102 .keywords: Mat, finite differences, coloring, view
103 @*/
104 PetscErrorCode  MatFDColoringView(MatFDColoring c,PetscViewer viewer)
105 {
106   PetscErrorCode    ierr;
107   PetscInt          i,j;
108   PetscBool         isdraw,iascii;
109   PetscViewerFormat format;
110 
111   PetscFunctionBegin;
112   PetscValidHeaderSpecific(c,MAT_FDCOLORING_CLASSID,1);
113   if (!viewer) {
114     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer);CHKERRQ(ierr);
115   }
116   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
117   PetscCheckSameComm(c,1,viewer,2);
118 
119   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
120   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
121   if (isdraw) {
122     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
123   } else if (iascii) {
124     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer);CHKERRQ(ierr);
125     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%G\n",c->error_rel);CHKERRQ(ierr);
126     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%G\n",c->umin);CHKERRQ(ierr);
127     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);CHKERRQ(ierr);
128 
129     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
130     if (format != PETSC_VIEWER_ASCII_INFO) {
131       PetscInt row,col,nz;
132       nz = 0;
133       for (i=0; i<c->ncolors; i++) {
134         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);CHKERRQ(ierr);
135         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr);
136         for (j=0; j<c->ncolumns[i]; j++) {
137           ierr = PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);CHKERRQ(ierr);
138         }
139         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr);
140         for (j=0; j<c->nrows[i]; j++) {
141           row  = c->matentry[nz].row;
142           col  = c->matentry[nz++].col;
143           ierr = PetscViewerASCIIPrintf(viewer,"      %D %D \n",row,col);CHKERRQ(ierr);
144         }
145       }
146     }
147     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
148   }
149   PetscFunctionReturn(0);
150 }
151 
152 #undef __FUNCT__
153 #define __FUNCT__ "MatFDColoringSetParameters"
154 /*@
155    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
156    a Jacobian matrix using finite differences.
157 
158    Logically Collective on MatFDColoring
159 
160    The Jacobian is estimated with the differencing approximation
161 .vb
162        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
163        h = error_rel*u[i]                 if  abs(u[i]) > umin
164          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
165        dx_{i} = (0, ... 1, .... 0)
166 .ve
167 
168    Input Parameters:
169 +  coloring - the coloring context
170 .  error_rel - relative error
171 -  umin - minimum allowable u-value magnitude
172 
173    Level: advanced
174 
175 .keywords: Mat, finite differences, coloring, set, parameters
176 
177 .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()
178 
179 @*/
180 PetscErrorCode  MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
181 {
182   PetscFunctionBegin;
183   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
184   PetscValidLogicalCollectiveReal(matfd,error,2);
185   PetscValidLogicalCollectiveReal(matfd,umin,3);
186   if (error != PETSC_DEFAULT) matfd->error_rel = error;
187   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
188   PetscFunctionReturn(0);
189 }
190 
191 
192 
193 #undef __FUNCT__
194 #define __FUNCT__ "MatFDColoringGetFunction"
195 /*@C
196    MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.
197 
198    Not Collective
199 
200    Input Parameters:
201 .  coloring - the coloring context
202 
203    Output Parameters:
204 +  f - the function
205 -  fctx - the optional user-defined function context
206 
207    Level: intermediate
208 
209 .keywords: Mat, Jacobian, finite differences, set, function
210 
211 .seealso: MatFDColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
212 
213 @*/
214 PetscErrorCode  MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
215 {
216   PetscFunctionBegin;
217   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
218   if (f) *f = matfd->f;
219   if (fctx) *fctx = matfd->fctx;
220   PetscFunctionReturn(0);
221 }
222 
223 #undef __FUNCT__
224 #define __FUNCT__ "MatFDColoringSetFunction"
225 /*@C
226    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
227 
228    Logically Collective on MatFDColoring
229 
230    Input Parameters:
231 +  coloring - the coloring context
232 .  f - the function
233 -  fctx - the optional user-defined function context
234 
235    Calling sequence of (*f) function:
236     For SNES:    PetscErrorCode (*f)(SNES,Vec,Vec,void*)
237     If not using SNES: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored
238 
239    Level: advanced
240 
241    Notes: This function is usually used automatically by SNES (when one uses SNESSetJacobian() with the argument
242      SNESComputeJacobianDefaultColor()) and only needs to be used by someone computing a matrix via coloring directly by
243      calling MatFDColoringApply()
244 
245    Fortran Notes:
246     In Fortran you must call MatFDColoringSetFunction() for a coloring object to
247   be used without SNES or within the SNES solvers.
248 
249 .keywords: Mat, Jacobian, finite differences, set, function
250 
251 .seealso: MatFDColoringCreate(), MatFDColoringGetFunction(), MatFDColoringSetFromOptions()
252 
253 @*/
254 PetscErrorCode  MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
255 {
256   PetscFunctionBegin;
257   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
258   matfd->f    = f;
259   matfd->fctx = fctx;
260   PetscFunctionReturn(0);
261 }
262 
263 #undef __FUNCT__
264 #define __FUNCT__ "MatFDColoringSetFromOptions"
265 /*@
266    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
267    the options database.
268 
269    Collective on MatFDColoring
270 
271    The Jacobian, F'(u), is estimated with the differencing approximation
272 .vb
273        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
274        h = error_rel*u[i]                 if  abs(u[i]) > umin
275          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
276        dx_{i} = (0, ... 1, .... 0)
277 .ve
278 
279    Input Parameter:
280 .  coloring - the coloring context
281 
282    Options Database Keys:
283 +  -mat_fd_coloring_err <err> - Sets <err> (square root
284            of relative error in the function)
285 .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
286 .  -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
287 .  -mat_fd_coloring_view - Activates basic viewing
288 .  -mat_fd_coloring_view ::ascii_info - Activates viewing info
289 -  -mat_fd_coloring_view draw - Activates drawing
290 
291     Level: intermediate
292 
293 .keywords: Mat, finite differences, parameters
294 
295 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
296 
297 @*/
298 PetscErrorCode  MatFDColoringSetFromOptions(MatFDColoring matfd)
299 {
300   PetscErrorCode ierr;
301   PetscBool      flg;
302   char           value[3];
303 
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
306 
307   ierr = PetscObjectOptionsBegin((PetscObject)matfd);CHKERRQ(ierr);
308   ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
309   ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
310   ierr = PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,3,&flg);CHKERRQ(ierr);
311   if (flg) {
312     if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
313     else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
314     else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
315   }
316   /* process any options handlers added with PetscObjectAddOptionsHandler() */
317   ierr = PetscObjectProcessOptionsHandlers((PetscObject)matfd);CHKERRQ(ierr);
318   PetscOptionsEnd();CHKERRQ(ierr);
319   PetscFunctionReturn(0);
320 }
321 
322 #undef __FUNCT__
323 #define __FUNCT__ "MatFDColoringViewFromOptions"
324 PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd,const char prefix[],const char optionname[])
325 {
326   PetscErrorCode    ierr;
327   PetscBool         flg;
328   PetscViewer       viewer;
329   PetscViewerFormat format;
330 
331   PetscFunctionBegin;
332   if (prefix) {
333     ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr);
334   } else {
335     ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),((PetscObject)fd)->prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr);
336   }
337   if (flg) {
338     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
339     ierr = MatFDColoringView(fd,viewer);CHKERRQ(ierr);
340     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
341     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
342   }
343   PetscFunctionReturn(0);
344 }
345 
346 #undef __FUNCT__
347 #define __FUNCT__ "MatFDColoringCreate"
348 /*@
349    MatFDColoringCreate - Creates a matrix coloring context for finite difference
350    computation of Jacobians.
351 
352    Collective on Mat
353 
354    Input Parameters:
355 +  mat - the matrix containing the nonzero structure of the Jacobian
356 -  iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMCreateColoring()
357 
358     Output Parameter:
359 .   color - the new coloring context
360 
361     Level: intermediate
362 
363 .seealso: MatFDColoringDestroy(),SNESComputeJacobianDefaultColor(), ISColoringCreate(),
364           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
365           MatFDColoringView(), MatFDColoringSetParameters(), MatGetColoring(), DMCreateColoring()
366 @*/
367 PetscErrorCode  MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
368 {
369   MatFDColoring  c;
370   MPI_Comm       comm;
371   PetscErrorCode ierr;
372   PetscInt       M,N;
373 
374   PetscFunctionBegin;
375   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
376   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
377   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
378   if (M != N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Only for square matrices");
379   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
380   ierr = PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_CLASSID,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr);
381 
382   c->ctype = iscoloring->ctype;
383 
384   if (mat->ops->fdcoloringcreate) {
385     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
386   } else SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
387 
388   ierr = MatGetVecs(mat,NULL,&c->w1);CHKERRQ(ierr);
389   ierr = PetscLogObjectParent((PetscObject)c,(PetscObject)c->w1);CHKERRQ(ierr);
390   ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr);
391   ierr = PetscLogObjectParent((PetscObject)c,(PetscObject)c->w2);CHKERRQ(ierr);
392 
393   c->error_rel    = PETSC_SQRT_MACHINE_EPSILON;
394   c->umin         = 100.0*PETSC_SQRT_MACHINE_EPSILON;
395   c->currentcolor = -1;
396   c->htype        = "wp";
397   c->fset         = PETSC_FALSE;
398 
399   *color = c;
400   ierr   = PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);CHKERRQ(ierr);
401   ierr   = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
402   PetscFunctionReturn(0);
403 }
404 
405 #undef __FUNCT__
406 #define __FUNCT__ "MatFDColoringDestroy"
407 /*@
408     MatFDColoringDestroy - Destroys a matrix coloring context that was created
409     via MatFDColoringCreate().
410 
411     Collective on MatFDColoring
412 
413     Input Parameter:
414 .   c - coloring context
415 
416     Level: intermediate
417 
418 .seealso: MatFDColoringCreate()
419 @*/
420 PetscErrorCode  MatFDColoringDestroy(MatFDColoring *c)
421 {
422   PetscErrorCode ierr;
423   PetscInt       i;
424 
425   PetscFunctionBegin;
426   if (!*c) PetscFunctionReturn(0);
427   if (--((PetscObject)(*c))->refct > 0) {*c = 0; PetscFunctionReturn(0);}
428 
429   for (i=0; i<(*c)->ncolors; i++) {
430     ierr = PetscFree((*c)->columns[i]);CHKERRQ(ierr);
431   }
432   ierr = PetscFree((*c)->ncolumns);CHKERRQ(ierr);
433   ierr = PetscFree((*c)->columns);CHKERRQ(ierr);
434   ierr = PetscFree((*c)->nrows);CHKERRQ(ierr);
435   ierr = PetscFree((*c)->matentry);CHKERRQ(ierr);
436   ierr = PetscFree((*c)->dy);CHKERRQ(ierr);
437   if ((*c)->vscale) {ierr = VecDestroy(&(*c)->vscale);CHKERRQ(ierr);}
438   ierr = VecDestroy(&(*c)->w1);CHKERRQ(ierr);
439   ierr = VecDestroy(&(*c)->w2);CHKERRQ(ierr);
440   ierr = VecDestroy(&(*c)->w3);CHKERRQ(ierr);
441   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
442   PetscFunctionReturn(0);
443 }
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "MatFDColoringGetPerturbedColumns"
447 /*@C
448     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
449       that are currently being perturbed.
450 
451     Not Collective
452 
453     Input Parameters:
454 .   coloring - coloring context created with MatFDColoringCreate()
455 
456     Output Parameters:
457 +   n - the number of local columns being perturbed
458 -   cols - the column indices, in global numbering
459 
460    Level: intermediate
461 
462 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()
463 
464 .keywords: coloring, Jacobian, finite differences
465 @*/
466 PetscErrorCode  MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,PetscInt *cols[])
467 {
468   PetscFunctionBegin;
469   if (coloring->currentcolor >= 0) {
470     *n    = coloring->ncolumns[coloring->currentcolor];
471     *cols = coloring->columns[coloring->currentcolor];
472   } else {
473     *n = 0;
474   }
475   PetscFunctionReturn(0);
476 }
477 
478 #undef __FUNCT__
479 #define __FUNCT__ "MatFDColoringApply"
480 /*@
481     MatFDColoringApply - Given a matrix for which a MatFDColoring context
482     has been created, computes the Jacobian for a function via finite differences.
483 
484     Collective on MatFDColoring
485 
486     Input Parameters:
487 +   mat - location to store Jacobian
488 .   coloring - coloring context created with MatFDColoringCreate()
489 .   x1 - location at which Jacobian is to be computed
490 -   sctx - context required by function, if this is being used with the SNES solver then it is SNES object, otherwise it is null
491 
492     Options Database Keys:
493 +    -mat_fd_type - "wp" or "ds"  (see MATMFFD_WP or MATMFFD_DS)
494 .    -mat_fd_coloring_view - Activates basic viewing or coloring
495 .    -mat_fd_coloring_view draw - Activates drawing of coloring
496 -    -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info
497 
498     Level: intermediate
499 
500 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction()
501 
502 .keywords: coloring, Jacobian, finite differences
503 @*/
504 PetscErrorCode  MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
505 {
506   PetscErrorCode ierr;
507   PetscBool      flg = PETSC_FALSE;
508 
509   PetscFunctionBegin;
510   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
511   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
512   PetscValidHeaderSpecific(x1,VEC_CLASSID,3);
513   if (!coloring->f) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
514   if (!J->ops->fdcoloringapply) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)J)->type_name);
515 
516   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
517   ierr = PetscOptionsGetBool(NULL,"-mat_fd_coloring_dont_rezero",&flg,NULL);CHKERRQ(ierr);
518   if (flg) {
519     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
520   } else {
521     PetscBool assembled;
522     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
523     if (assembled) {
524       ierr = MatZeroEntries(J);CHKERRQ(ierr);
525     }
526   }
527 
528   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
529   ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr);
530   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
531   PetscFunctionReturn(0);
532 }
533