xref: /petsc/src/mat/matfd/fdmatrix.c (revision 4effdb2689a9c22ad471da24694f3883d503f620)
1 #define PETSCMAT_DLL
2 
3 /*
4    This is where the abstract matrix operations are defined that are
5   used for finite difference computations of Jacobians using coloring.
6 */
7 
8 #include "src/mat/matimpl.h"        /*I "petscmat.h" I*/
9 
10 /* Logging support */
11 PetscCookie PETSCMAT_DLLEXPORT MAT_FDCOLORING_COOKIE = 0;
12 
13 #undef __FUNCT__
14 #define __FUNCT__ "MatFDColoringSetF"
15 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringSetF(MatFDColoring fd,Vec F)
16 {
17   PetscFunctionBegin;
18   fd->F = F;
19   PetscFunctionReturn(0);
20 }
21 
22 #undef __FUNCT__
23 #define __FUNCT__ "MatFDColoringView_Draw_Zoom"
24 static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
25 {
26   MatFDColoring  fd = (MatFDColoring)Aa;
27   PetscErrorCode ierr;
28   PetscInt       i,j;
29   PetscReal      x,y;
30 
31   PetscFunctionBegin;
32 
33   /* loop over colors  */
34   for (i=0; i<fd->ncolors; i++) {
35     for (j=0; j<fd->nrows[i]; j++) {
36       y = fd->M - fd->rows[i][j] - fd->rstart;
37       x = fd->columnsforrow[i][j];
38       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
39     }
40   }
41   PetscFunctionReturn(0);
42 }
43 
44 #undef __FUNCT__
45 #define __FUNCT__ "MatFDColoringView_Draw"
46 static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
47 {
48   PetscErrorCode ierr;
49   PetscTruth     isnull;
50   PetscDraw      draw;
51   PetscReal      xr,yr,xl,yl,h,w;
52 
53   PetscFunctionBegin;
54   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
55   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
56 
57   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
58 
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   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
62   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
63   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
64   PetscFunctionReturn(0);
65 }
66 
67 #undef __FUNCT__
68 #define __FUNCT__ "MatFDColoringView"
69 /*@C
70    MatFDColoringView - Views a finite difference coloring context.
71 
72    Collective on MatFDColoring
73 
74    Input  Parameters:
75 +  c - the coloring context
76 -  viewer - visualization context
77 
78    Level: intermediate
79 
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
88 
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.
93 
94 .seealso: MatFDColoringCreate()
95 
96 .keywords: Mat, finite differences, coloring, view
97 @*/
98 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringView(MatFDColoring c,PetscViewer viewer)
99 {
100   PetscErrorCode    ierr;
101   PetscInt          i,j;
102   PetscTruth        isdraw,iascii;
103   PetscViewerFormat format;
104 
105   PetscFunctionBegin;
106   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE,1);
107   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(c->comm);
108   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
109   PetscCheckSameComm(c,1,viewer,2);
110 
111   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
112   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
113   if (isdraw) {
114     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
115   } else if (iascii) {
116     ierr = PetscViewerASCIIPrintf(viewer,"MatFDColoring Object:\n");CHKERRQ(ierr);
117     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%G\n",c->error_rel);CHKERRQ(ierr);
118     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%G\n",c->umin);CHKERRQ(ierr);
119     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);CHKERRQ(ierr);
120 
121     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
122     if (format != PETSC_VIEWER_ASCII_INFO) {
123       for (i=0; i<c->ncolors; i++) {
124         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);CHKERRQ(ierr);
125         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr);
126         for (j=0; j<c->ncolumns[i]; j++) {
127           ierr = PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);CHKERRQ(ierr);
128         }
129         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr);
130         for (j=0; j<c->nrows[i]; j++) {
131           ierr = PetscViewerASCIIPrintf(viewer,"      %D %D \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
132         }
133       }
134     }
135     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
136   } else {
137     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
138   }
139   PetscFunctionReturn(0);
140 }
141 
142 #undef __FUNCT__
143 #define __FUNCT__ "MatFDColoringSetParameters"
144 /*@
145    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
146    a Jacobian matrix using finite differences.
147 
148    Collective on MatFDColoring
149 
150    The Jacobian is estimated with the differencing approximation
151 .vb
152        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
153        h = error_rel*u[i]                 if  abs(u[i]) > umin
154          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
155        dx_{i} = (0, ... 1, .... 0)
156 .ve
157 
158    Input Parameters:
159 +  coloring - the coloring context
160 .  error_rel - relative error
161 -  umin - minimum allowable u-value magnitude
162 
163    Level: advanced
164 
165 .keywords: Mat, finite differences, coloring, set, parameters
166 
167 .seealso: MatFDColoringCreate()
168 @*/
169 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
170 {
171   PetscFunctionBegin;
172   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
173 
174   if (error != PETSC_DEFAULT) matfd->error_rel = error;
175   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
176   PetscFunctionReturn(0);
177 }
178 
179 #undef __FUNCT__
180 #define __FUNCT__ "MatFDColoringSetFrequency"
181 /*@
182    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
183    matrices.
184 
185    Collective on MatFDColoring
186 
187    Input Parameters:
188 +  coloring - the coloring context
189 -  freq - frequency (default is 1)
190 
191    Options Database Keys:
192 .  -mat_fd_coloring_freq <freq>  - Sets coloring frequency
193 
194    Level: advanced
195 
196    Notes:
197    Using a modified Newton strategy, where the Jacobian remains fixed for several
198    iterations, can be cost effective in terms of overall nonlinear solution
199    efficiency.  This parameter indicates that a new Jacobian will be computed every
200    <freq> nonlinear iterations.
201 
202 .keywords: Mat, finite differences, coloring, set, frequency
203 
204 .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency(), MatFDColoringSetRecompute()
205 @*/
206 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringSetFrequency(MatFDColoring matfd,PetscInt freq)
207 {
208   PetscFunctionBegin;
209   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
210 
211   matfd->freq = freq;
212   PetscFunctionReturn(0);
213 }
214 
215 #undef __FUNCT__
216 #define __FUNCT__ "MatFDColoringGetFrequency"
217 /*@
218    MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian
219    matrices.
220 
221    Not Collective
222 
223    Input Parameters:
224 .  coloring - the coloring context
225 
226    Output Parameters:
227 .  freq - frequency (default is 1)
228 
229    Options Database Keys:
230 .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
231 
232    Level: advanced
233 
234    Notes:
235    Using a modified Newton strategy, where the Jacobian remains fixed for several
236    iterations, can be cost effective in terms of overall nonlinear solution
237    efficiency.  This parameter indicates that a new Jacobian will be computed every
238    <freq> nonlinear iterations.
239 
240 .keywords: Mat, finite differences, coloring, get, frequency
241 
242 .seealso: MatFDColoringSetFrequency()
243 @*/
244 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringGetFrequency(MatFDColoring matfd,PetscInt *freq)
245 {
246   PetscFunctionBegin;
247   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
248   *freq = matfd->freq;
249   PetscFunctionReturn(0);
250 }
251 
252 #undef __FUNCT__
253 #define __FUNCT__ "MatFDColoringGetFunction"
254 /*@C
255    MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.
256 
257    Collective on MatFDColoring
258 
259    Input Parameters:
260 .  coloring - the coloring context
261 
262    Output Parameters:
263 +  f - the function
264 -  fctx - the optional user-defined function context
265 
266    Level: intermediate
267 
268 .keywords: Mat, Jacobian, finite differences, set, function
269 @*/
270 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
271 {
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
274   if (f) *f = matfd->f;
275   if (fctx) *fctx = matfd->fctx;
276   PetscFunctionReturn(0);
277 }
278 
279 #undef __FUNCT__
280 #define __FUNCT__ "MatFDColoringSetFunction"
281 /*@C
282    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
283 
284    Collective on MatFDColoring
285 
286    Input Parameters:
287 +  coloring - the coloring context
288 .  f - the function
289 -  fctx - the optional user-defined function context
290 
291    Level: intermediate
292 
293    Notes:
294     In Fortran you must call MatFDColoringSetFunctionSNES() for a coloring object to
295   be used with the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used
296   with the TS solvers.
297 
298 .keywords: Mat, Jacobian, finite differences, set, function
299 @*/
300 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
301 {
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
304   matfd->f    = f;
305   matfd->fctx = fctx;
306   PetscFunctionReturn(0);
307 }
308 
309 #undef __FUNCT__
310 #define __FUNCT__ "MatFDColoringSetFromOptions"
311 /*@
312    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
313    the options database.
314 
315    Collective on MatFDColoring
316 
317    The Jacobian, F'(u), is estimated with the differencing approximation
318 .vb
319        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
320        h = error_rel*u[i]                 if  abs(u[i]) > umin
321          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
322        dx_{i} = (0, ... 1, .... 0)
323 .ve
324 
325    Input Parameter:
326 .  coloring - the coloring context
327 
328    Options Database Keys:
329 +  -mat_fd_coloring_err <err> - Sets <err> (square root
330            of relative error in the function)
331 .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
332 .  -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian
333 .  -mat_fd_type - "wp" or "ds" (see MATSNESMF_WP or MATSNESMF_DS)
334 .  -mat_fd_coloring_view - Activates basic viewing
335 .  -mat_fd_coloring_view_info - Activates viewing info
336 -  -mat_fd_coloring_view_draw - Activates drawing
337 
338     Level: intermediate
339 
340 .keywords: Mat, finite differences, parameters
341 
342 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
343 
344 @*/
345 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringSetFromOptions(MatFDColoring matfd)
346 {
347   PetscErrorCode ierr;
348   PetscTruth     flg;
349   char           value[3];
350   PetscMPIInt    size;
351   const char     *isctypes[] = {"IS_COLORING_LOCAL","IS_COLORING_GHOSTED"};
352   PetscInt       isctype;
353 
354   PetscFunctionBegin;
355   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
356 
357   ierr = PetscOptionsBegin(matfd->comm,matfd->prefix,"Jacobian computation via finite differences option","MatFD");CHKERRQ(ierr);
358     ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
359     ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
360     ierr = PetscOptionsInt("-mat_fd_coloring_freq","How often Jacobian is recomputed","MatFDColoringSetFrequency",matfd->freq,&matfd->freq,0);CHKERRQ(ierr);
361 
362     ierr = MPI_Comm_size(matfd->comm,&size);CHKERRQ(ierr);
363     /* set default coloring type */
364     if (size == 1){
365       isctype      = 0; /* IS_COLORING_LOCAL */
366     } else {
367       isctype      = 0; /* should be 1, IS_COLORING_GHOSTED */
368     }
369     ierr = PetscOptionsEList("-mat_fd_coloring_type","Type of MatFDColoring","None",isctypes,2,isctypes[isctype],&isctype,PETSC_NULL);CHKERRQ(ierr);
370     matfd->ctype = (ISColoringType)isctype;
371 
372     ierr = PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,2,&flg);CHKERRQ(ierr);
373     if (flg) {
374       if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
375       else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
376       else SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
377     }
378     /* not used here; but so they are presented in the GUI */
379     ierr = PetscOptionsName("-mat_fd_coloring_view","Print entire datastructure used for Jacobian","None",0);CHKERRQ(ierr);
380     ierr = PetscOptionsName("-mat_fd_coloring_view_info","Print number of colors etc for Jacobian","None",0);CHKERRQ(ierr);
381     ierr = PetscOptionsName("-mat_fd_coloring_view_draw","Plot nonzero structure ofJacobian","None",0);CHKERRQ(ierr);
382   PetscOptionsEnd();CHKERRQ(ierr);
383   PetscFunctionReturn(0);
384 }
385 
386 #undef __FUNCT__
387 #define __FUNCT__ "MatFDColoringView_Private"
388 PetscErrorCode MatFDColoringView_Private(MatFDColoring fd)
389 {
390   PetscErrorCode ierr;
391   PetscTruth     flg;
392 
393   PetscFunctionBegin;
394   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr);
395   if (flg) {
396     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
397   }
398   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr);
399   if (flg) {
400     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(fd->comm),PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
401     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
402     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
403   }
404   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr);
405   if (flg) {
406     ierr = MatFDColoringView(fd,PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
407     ierr = PetscViewerFlush(PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
408   }
409   PetscFunctionReturn(0);
410 }
411 
412 #undef __FUNCT__
413 #define __FUNCT__ "MatFDColoringCreate"
414 /*@
415    MatFDColoringCreate - Creates a matrix coloring context for finite difference
416    computation of Jacobians.
417 
418    Collective on Mat
419 
420    Input Parameters:
421 +  mat - the matrix containing the nonzero structure of the Jacobian
422 -  iscoloring - the coloring of the matrix
423 
424     Output Parameter:
425 .   color - the new coloring context
426 
427     Level: intermediate
428 
429 .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
430           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
431           MatFDColoringSetFrequency(), MatFDColoringSetRecompute(), MatFDColoringView(),
432           MatFDColoringSetParameters()
433 @*/
434 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
435 {
436   MatFDColoring  c;
437   MPI_Comm       comm;
438   PetscErrorCode ierr;
439   PetscInt       M,N;
440   PetscMPIInt    size;
441 
442   PetscFunctionBegin;
443   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
444   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
445   if (M != N) SETERRQ(PETSC_ERR_SUP,"Only for square matrices");
446 
447   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
448   ierr = PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr);
449 
450   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
451   c->ctype = iscoloring->ctype;
452   if (size == 1) c->ctype = iscoloring->ctype = IS_COLORING_LOCAL;
453 
454   if (mat->ops->fdcoloringcreate) {
455     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
456   } else {
457     SETERRQ(PETSC_ERR_SUP,"Code not yet written for this matrix type");
458   }
459 
460   ierr = MatGetVecs(mat,PETSC_NULL,&c->w1);CHKERRQ(ierr);
461   ierr = PetscLogObjectParent(c,c->w1);CHKERRQ(ierr);
462   ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr);
463   ierr = PetscLogObjectParent(c,c->w2);CHKERRQ(ierr);
464 
465   c->error_rel         = PETSC_SQRT_MACHINE_EPSILON;
466   c->umin              = 100.0*PETSC_SQRT_MACHINE_EPSILON;
467   c->freq              = 1;
468   c->usersetsrecompute = PETSC_FALSE;
469   c->recompute         = PETSC_FALSE;
470   c->currentcolor      = -1;
471   c->htype             = "wp";
472 
473   *color = c;
474   ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
475   PetscFunctionReturn(0);
476 }
477 
478 #undef __FUNCT__
479 #define __FUNCT__ "MatFDColoringDestroy"
480 /*@
481     MatFDColoringDestroy - Destroys a matrix coloring context that was created
482     via MatFDColoringCreate().
483 
484     Collective on MatFDColoring
485 
486     Input Parameter:
487 .   c - coloring context
488 
489     Level: intermediate
490 
491 .seealso: MatFDColoringCreate()
492 @*/
493 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringDestroy(MatFDColoring c)
494 {
495   PetscErrorCode ierr;
496   PetscInt       i;
497 
498   PetscFunctionBegin;
499   if (--c->refct > 0) PetscFunctionReturn(0);
500 
501   for (i=0; i<c->ncolors; i++) {
502     ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);
503     ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);
504     ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);
505     if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow[i]);CHKERRQ(ierr);}
506   }
507   ierr = PetscFree(c->ncolumns);CHKERRQ(ierr);
508   ierr = PetscFree(c->columns);CHKERRQ(ierr);
509   ierr = PetscFree(c->nrows);CHKERRQ(ierr);
510   ierr = PetscFree(c->rows);CHKERRQ(ierr);
511   ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr);
512   ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);
513   if (c->vscale)       {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);}
514   if (c->w1) {
515     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
516     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
517   }
518   if (c->w3){
519     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
520   }
521   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
522   PetscFunctionReturn(0);
523 }
524 
525 #undef __FUNCT__
526 #define __FUNCT__ "MatFDColoringGetPerturbedColumns"
527 /*@C
528     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
529       that are currently being perturbed.
530 
531     Not Collective
532 
533     Input Parameters:
534 .   coloring - coloring context created with MatFDColoringCreate()
535 
536     Output Parameters:
537 +   n - the number of local columns being perturbed
538 -   cols - the column indices, in global numbering
539 
540    Level: intermediate
541 
542 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()
543 
544 .keywords: coloring, Jacobian, finite differences
545 @*/
546 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,PetscInt *cols[])
547 {
548   PetscFunctionBegin;
549   if (coloring->currentcolor >= 0) {
550     *n    = coloring->ncolumns[coloring->currentcolor];
551     *cols = coloring->columns[coloring->currentcolor];
552   } else {
553     *n = 0;
554   }
555   PetscFunctionReturn(0);
556 }
557 
558 #include "petscda.h"      /*I      "petscda.h"    I*/
559 
560 #undef __FUNCT__
561 #define __FUNCT__ "MatFDColoringApply"
562 /*@
563     MatFDColoringApply - Given a matrix for which a MatFDColoring context
564     has been created, computes the Jacobian for a function via finite differences.
565 
566     Collective on MatFDColoring
567 
568     Input Parameters:
569 +   mat - location to store Jacobian
570 .   coloring - coloring context created with MatFDColoringCreate()
571 .   x1 - location at which Jacobian is to be computed
572 -   sctx - optional context required by function (actually a SNES context)
573 
574     Options Database Keys:
575 +    -mat_fd_coloring_freq <freq> - Sets coloring frequency
576 .    -mat_fd_type - "wp" or "ds"  (see MATSNESMF_WP or MATSNESMF_DS)
577 .    -mat_fd_coloring_view - Activates basic viewing or coloring
578 .    -mat_fd_coloring_view_draw - Activates drawing of coloring
579 -    -mat_fd_coloring_view_info - Activates viewing of coloring info
580 
581     Level: intermediate
582 
583 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
584 
585 .keywords: coloring, Jacobian, finite differences
586 @*/
587 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
588 {
589   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
590   PetscErrorCode ierr;
591   PetscInt       k,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
592   PetscScalar    dx,*y,*xx,*w3_array;
593   PetscScalar    *vscale_array;
594   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin,unorm;
595   Vec            w1=coloring->w1,w2=coloring->w2,w3;
596   void           *fctx = coloring->fctx;
597   PetscTruth     flg;
598   PetscInt       ctype=coloring->ctype,N,col_start,col_end;
599   Vec            x1_tmp;
600   // remove !
601   PetscMPIInt rank;
602   PetscInt    prid=10;
603   /*  ex5
604   PetscTruth  fd_jacobian_ghost=PETSC_FALSE;
605   DA          da;
606   */
607 
608   PetscFunctionBegin;
609 
610     ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
611     ierr = PetscOptionsGetInt(PETSC_NULL,"-prid",&prid,PETSC_NULL);CHKERRQ(ierr);
612 
613   PetscValidHeaderSpecific(J,MAT_COOKIE,1);
614   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE,2);
615   PetscValidHeaderSpecific(x1,VEC_COOKIE,3);
616   if (!f) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
617 
618   if (coloring->usersetsrecompute) {
619     if (!coloring->recompute) {
620       *flag = SAME_PRECONDITIONER;
621       ierr = PetscInfo(J,"Skipping Jacobian, since user called MatFDColorSetRecompute()\n");CHKERRQ(ierr);
622       PetscFunctionReturn(0);
623     } else {
624       coloring->recompute = PETSC_FALSE;
625     }
626   }
627 
628   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
629   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
630   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
631   if (flg) {
632     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
633   } else {
634     PetscTruth assembled;
635     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
636     if (assembled) {
637       ierr = MatZeroEntries(J);CHKERRQ(ierr);
638     }
639   }
640 
641   x1_tmp = x1;
642   /* used for ex5.c
643   ierr = PetscOptionsGetTruth(PETSC_NULL,"-fd_jacobian_ghost",&fd_jacobian_ghost,0);CHKERRQ(ierr);
644   if (fd_jacobian_ghost){
645     da = *(DA*)fctx;
646     /* CANNOT USE DA OPs from Mat code */
647     /*    ierr = DAGetLocalVector(da,&x1_tmp);CHKERRQ(ierr); */
648   }
649   */
650 
651   if (ctype == IS_COLORING_GHOSTED && !coloring->vscale){
652     ierr = VecDuplicate(x1_tmp,&coloring->vscale);CHKERRQ(ierr);
653   }
654 
655   /*
656     This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
657     coloring->F for the coarser grids from the finest
658   */
659   if (coloring->F) {
660     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
661     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
662     if (m1 != m2) {
663       coloring->F = 0;
664       }
665     }
666 
667   if (coloring->htype[0] == 'w') { /* tacky test; need to make systematic if we add other approaches to computing h*/
668     ierr = VecNorm(x1_tmp,NORM_2,&unorm);CHKERRQ(ierr);
669   }
670   ierr = VecGetOwnershipRange(w1,&start,&end);CHKERRQ(ierr); /* OwnershipRange is used by ghosted x! */
671 
672   /* Set w1 = F(x1) */
673   if (coloring->F) {
674     w1          = coloring->F; /* use already computed value of function */
675     coloring->F = 0;
676   } else {
677     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
678     ierr = (*f)(sctx,x1_tmp,w1,fctx);CHKERRQ(ierr);
679     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
680   }
681 
682   if (!coloring->w3) {
683     ierr = VecDuplicate(x1_tmp,&coloring->w3);CHKERRQ(ierr);
684     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
685   }
686   w3 = coloring->w3;
687 
688     /* Compute all the local scale factors, including ghost points */
689   ierr = VecGetLocalSize(x1_tmp,&N);CHKERRQ(ierr);
690   ierr = VecGetArray(x1_tmp,&xx);CHKERRQ(ierr);
691   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
692   if (ctype == IS_COLORING_GHOSTED){
693     col_start = 0; col_end = N;
694   } else if (ctype == IS_COLORING_LOCAL){
695     xx = xx - start;
696     vscale_array = vscale_array - start;
697     col_start = start; col_end = N + start;
698   }
699   for (col=col_start; col<col_end; col++){
700     /* Loop over each local column, vscale[col] = 1./(epsilon*dx[col]) */
701     if (coloring->htype[0] == 'w') {
702       dx = 1.0 + unorm;
703     } else {
704       dx  = xx[col];
705     }
706     if (dx == 0.0) dx = 1.0;
707 #if !defined(PETSC_USE_COMPLEX)
708     if (dx < umin && dx >= 0.0)      dx = umin;
709     else if (dx < 0.0 && dx > -umin) dx = -umin;
710 #else
711     if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
712     else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
713 #endif
714     dx               *= epsilon;
715     vscale_array[col] = 1.0/dx;
716   }
717   if (ctype == IS_COLORING_LOCAL)  vscale_array = vscale_array + start;
718   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
719   if (ctype == IS_COLORING_LOCAL){
720     ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
721     ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
722   }
723 
724   if (coloring->vscaleforrow) {
725     vscaleforrow = coloring->vscaleforrow;
726   } else {
727     SETERRQ(PETSC_ERR_ARG_NULL,"Null Object: coloring->vscaleforrow");
728   }
729 
730   /*
731     Loop over each color
732   */
733   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
734   for (k=0; k<coloring->ncolors; k++) {
735     coloring->currentcolor = k;
736     ierr = VecCopy(x1_tmp,w3);CHKERRQ(ierr);
737     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);
738     if (ctype == IS_COLORING_LOCAL) w3_array = w3_array - start;
739 
740     if (prid == rank) printf(" [%d] color %d \n -----------\n",rank,k);
741     /*
742       Loop over each column associated with color
743       adding the perturbation to the vector w3.
744     */
745     for (l=0; l<coloring->ncolumns[k]; l++) {
746       col = coloring->columns[k][l];    /* local column of the matrix we are probing for */
747       if (coloring->htype[0] == 'w') {
748         dx = 1.0 + unorm;
749       } else {
750         dx  = xx[col];
751       }
752       if (dx == 0.0) dx = 1.0;
753 #if !defined(PETSC_USE_COMPLEX)
754       if (dx < umin && dx >= 0.0)      dx = umin;
755       else if (dx < 0.0 && dx > -umin) dx = -umin;
756 #else
757       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
758       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
759 #endif
760       dx            *= epsilon;
761       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_ERR_PLIB,"Computed 0 differencing parameter");
762       w3_array[col] += dx;
763     }
764     if (ctype == IS_COLORING_LOCAL) w3_array = w3_array + start;
765     ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
766 
767     /*
768       Evaluate function at w3 = x1 + dx (here dx is a vector of perturbations)
769                            w2 = F(x1 + dx) - F(x1)
770     */
771     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
772     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
773     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
774     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
775 
776     /*
777       Loop over rows of vector, putting results into Jacobian matrix
778     */
779     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
780     for (l=0; l<coloring->nrows[k]; l++) {
781       row    = coloring->rows[k][l];             /* local row index */
782       col    = coloring->columnsforrow[k][l];    /* global column index */
783       y[row] *= vscale_array[vscaleforrow[k][l]];
784       srow   = row + start;
785       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
786     }
787     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
788   } // endof for each color
789   if (ctype == IS_COLORING_LOCAL) xx = xx + start;
790   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
791   ierr = VecRestoreArray(x1_tmp,&xx);CHKERRQ(ierr);
792 
793   coloring->currentcolor = -1;
794   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
795   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
796     //ierr = MatView(J,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
797   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
798 
799   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test",&flg);CHKERRQ(ierr);
800   if (flg) {
801     ierr = MatNullSpaceTest(J->nullsp,J);CHKERRQ(ierr);
802   }
803   ierr = MatFDColoringView_Private(coloring);CHKERRQ(ierr);
804 
805 #if !defined(PETSC_USE_COMPLEX)
806   if (fd_jacobian_ghost){ /* ex5 */
807     /*    ierr = DARestoreLocalVector(da,&x1_tmp);CHKERRQ(ierr); */
808   }
809   */
810   PetscFunctionReturn(0);
811 }
812 
813 #undef __FUNCT__
814 #define __FUNCT__ "MatFDColoringApplyTS"
815 /*@
816     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
817     has been created, computes the Jacobian for a function via finite differences.
818 
819    Collective on Mat, MatFDColoring, and Vec
820 
821     Input Parameters:
822 +   mat - location to store Jacobian
823 .   coloring - coloring context created with MatFDColoringCreate()
824 .   x1 - location at which Jacobian is to be computed
825 -   sctx - optional context required by function (actually a SNES context)
826 
827    Options Database Keys:
828 .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
829 
830    Level: intermediate
831 
832 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
833 
834 .keywords: coloring, Jacobian, finite differences
835 @*/
836 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
837 {
838   PetscErrorCode (*f)(void*,PetscReal,Vec,Vec,void*)=(PetscErrorCode (*)(void*,PetscReal,Vec,Vec,void *))coloring->f;
839   PetscErrorCode ierr;
840   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow;
841   PetscScalar    dx,*y,*xx,*w3_array;
842   PetscScalar    *vscale_array;
843   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
844   Vec            w1,w2,w3;
845   void           *fctx = coloring->fctx;
846   PetscTruth     flg;
847 
848   PetscFunctionBegin;
849   PetscValidHeaderSpecific(J,MAT_COOKIE,1);
850   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE,2);
851   PetscValidHeaderSpecific(x1,VEC_COOKIE,4);
852 
853   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
854   if (!coloring->w1) {
855     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
856     ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr);
857     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
858     ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr);
859     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
860     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
861   }
862   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
863 
864   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
865   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
866   if (flg) {
867     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
868   } else {
869     PetscTruth assembled;
870     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
871     if (assembled) {
872       ierr = MatZeroEntries(J);CHKERRQ(ierr);
873     }
874   }
875 
876   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
877   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
878   ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
879   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
880   ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
881 
882   /*
883       Compute all the scale factors and share with other processors
884   */
885   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
886   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
887   for (k=0; k<coloring->ncolors; k++) {
888     /*
889        Loop over each column associated with color adding the
890        perturbation to the vector w3.
891     */
892     for (l=0; l<coloring->ncolumns[k]; l++) {
893       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
894       dx  = xx[col];
895       if (dx == 0.0) dx = 1.0;
896 #if !defined(PETSC_USE_COMPLEX)
897       if (dx < umin && dx >= 0.0)      dx = umin;
898       else if (dx < 0.0 && dx > -umin) dx = -umin;
899 #else
900       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
901       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
902 #endif
903       dx                *= epsilon;
904       vscale_array[col] = 1.0/dx;
905     }
906   }
907   vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
908   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
909   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
910 
911   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
912   else                        vscaleforrow = coloring->columnsforrow;
913 
914   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
915   /*
916       Loop over each color
917   */
918   for (k=0; k<coloring->ncolors; k++) {
919     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
920     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
921     /*
922        Loop over each column associated with color adding the
923        perturbation to the vector w3.
924     */
925     for (l=0; l<coloring->ncolumns[k]; l++) {
926       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
927       dx  = xx[col];
928       if (dx == 0.0) dx = 1.0;
929 #if !defined(PETSC_USE_COMPLEX)
930       if (dx < umin && dx >= 0.0)      dx = umin;
931       else if (dx < 0.0 && dx > -umin) dx = -umin;
932 #else
933       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
934       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
935 #endif
936       dx            *= epsilon;
937       w3_array[col] += dx;
938     }
939     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
940 
941     /*
942        Evaluate function at x1 + dx (here dx is a vector of perturbations)
943     */
944     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
945     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
946     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
947     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
948 
949     /*
950        Loop over rows of vector, putting results into Jacobian matrix
951     */
952     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
953     for (l=0; l<coloring->nrows[k]; l++) {
954       row    = coloring->rows[k][l];
955       col    = coloring->columnsforrow[k][l];
956       y[row] *= vscale_array[vscaleforrow[k][l]];
957       srow   = row + start;
958       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
959     }
960     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
961   }
962   ierr  = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
963   xx    = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
964   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
965   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
966   ierr  = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
967   PetscFunctionReturn(0);
968 }
969 
970 
971 #undef __FUNCT__
972 #define __FUNCT__ "MatFDColoringSetRecompute()"
973 /*@C
974    MatFDColoringSetRecompute - Indicates that the next time a Jacobian preconditioner
975      is needed it sholuld be recomputed. Once this is called and the new Jacobian is computed
976      no additional Jacobian's will be computed (the same one will be used) until this is
977      called again.
978 
979    Collective on MatFDColoring
980 
981    Input  Parameters:
982 .  c - the coloring context
983 
984    Level: intermediate
985 
986    Notes: The MatFDColoringSetFrequency() is ignored once this is called
987 
988 .seealso: MatFDColoringCreate(), MatFDColoringSetFrequency()
989 
990 .keywords: Mat, finite differences, coloring
991 @*/
992 PetscErrorCode PETSCMAT_DLLEXPORT MatFDColoringSetRecompute(MatFDColoring c)
993 {
994   PetscFunctionBegin;
995   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE,1);
996   c->usersetsrecompute = PETSC_TRUE;
997   c->recompute         = PETSC_TRUE;
998   PetscFunctionReturn(0);
999 }
1000 
1001 
1002