xref: /petsc/src/mat/matfd/fdmatrix.c (revision 487a658c8b32ba712a1dc8280daad2fd70c1dcd9)
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 #include <petsc/private/isimpl.h>
9 
10 PetscErrorCode  MatFDColoringSetF(MatFDColoring fd,Vec F)
11 {
12   PetscErrorCode ierr;
13 
14   PetscFunctionBegin;
15   if (F) {
16     ierr     = VecCopy(F,fd->w1);CHKERRQ(ierr);
17     fd->fset = PETSC_TRUE;
18   } else {
19     fd->fset = PETSC_FALSE;
20   }
21   PetscFunctionReturn(0);
22 }
23 
24 #include <petscdraw.h>
25 static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
26 {
27   MatFDColoring  fd = (MatFDColoring)Aa;
28   PetscErrorCode ierr;
29   PetscInt       i,j,nz,row;
30   PetscReal      x,y;
31   MatEntry       *Jentry=fd->matentry;
32 
33   PetscFunctionBegin;
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       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
42     }
43   }
44   PetscFunctionReturn(0);
45 }
46 
47 static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
48 {
49   PetscErrorCode ierr;
50   PetscBool      isnull;
51   PetscDraw      draw;
52   PetscReal      xr,yr,xl,yl,h,w;
53 
54   PetscFunctionBegin;
55   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
56   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
57   if (isnull) PetscFunctionReturn(0);
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 = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
63   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
64   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",NULL);CHKERRQ(ierr);
65   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
66   PetscFunctionReturn(0);
67 }
68 
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  MatFDColoringView(MatFDColoring c,PetscViewer viewer)
99 {
100   PetscErrorCode    ierr;
101   PetscInt          i,j;
102   PetscBool         isdraw,iascii;
103   PetscViewerFormat format;
104 
105   PetscFunctionBegin;
106   PetscValidHeaderSpecific(c,MAT_FDCOLORING_CLASSID,1);
107   if (!viewer) {
108     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer);CHKERRQ(ierr);
109   }
110   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
111   PetscCheckSameComm(c,1,viewer,2);
112 
113   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
114   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
115   if (isdraw) {
116     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
117   } else if (iascii) {
118     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer);CHKERRQ(ierr);
119     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",(double)c->error_rel);CHKERRQ(ierr);
120     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%g\n",(double)c->umin);CHKERRQ(ierr);
121     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);CHKERRQ(ierr);
122 
123     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
124     if (format != PETSC_VIEWER_ASCII_INFO) {
125       PetscInt row,col,nz;
126       nz = 0;
127       for (i=0; i<c->ncolors; i++) {
128         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);CHKERRQ(ierr);
129         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr);
130         for (j=0; j<c->ncolumns[i]; j++) {
131           ierr = PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);CHKERRQ(ierr);
132         }
133         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr);
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             ierr = PetscViewerASCIIPrintf(viewer,"      %D %D \n",row,col);CHKERRQ(ierr);
139           }
140         }
141       }
142     }
143     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
144   }
145   PetscFunctionReturn(0);
146 }
147 
148 /*@
149    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
150    a Jacobian matrix using finite differences.
151 
152    Logically Collective on MatFDColoring
153 
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        htype = 'ds':
158          h = error_rel*u[i]                 if  abs(u[i]) > umin
159            = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
160          dx_{i} = (0, ... 1, .... 0)
161 
162        htype = 'wp':
163          h = error_rel * sqrt(1 + ||u||)
164 .ve
165 
166    Input Parameters:
167 +  coloring - the coloring context
168 .  error_rel - relative error
169 -  umin - minimum allowable u-value magnitude
170 
171    Level: advanced
172 
173 .keywords: Mat, finite differences, coloring, set, parameters
174 
175 .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()
176 
177 @*/
178 PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
179 {
180   PetscFunctionBegin;
181   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
182   PetscValidLogicalCollectiveReal(matfd,error,2);
183   PetscValidLogicalCollectiveReal(matfd,umin,3);
184   if (error != PETSC_DEFAULT) matfd->error_rel = error;
185   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
186   PetscFunctionReturn(0);
187 }
188 
189 /*@
190    MatFDColoringSetBlockSize - Sets block size for efficient inserting entries of Jacobian matrix.
191 
192    Logically Collective on MatFDColoring
193 
194    Input Parameters:
195 +  coloring - the coloring context
196 .  brows - number of rows in the block
197 -  bcols - number of columns in the block
198 
199    Level: intermediate
200 
201 .keywords: Mat, coloring
202 
203 .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()
204 
205 @*/
206 PetscErrorCode MatFDColoringSetBlockSize(MatFDColoring matfd,PetscInt brows,PetscInt bcols)
207 {
208   PetscFunctionBegin;
209   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
210   PetscValidLogicalCollectiveInt(matfd,brows,2);
211   PetscValidLogicalCollectiveInt(matfd,bcols,3);
212   if (brows != PETSC_DEFAULT) matfd->brows = brows;
213   if (bcols != PETSC_DEFAULT) matfd->bcols = bcols;
214   PetscFunctionReturn(0);
215 }
216 
217 /*@
218    MatFDColoringSetUp - Sets up the internal data structures of matrix coloring context for the later use.
219 
220    Collective on Mat
221 
222    Input Parameters:
223 +  mat - the matrix containing the nonzero structure of the Jacobian
224 .  iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMCreateColoring()
225 -  color - the matrix coloring context
226 
227    Level: beginner
228 
229 .keywords: MatFDColoring, setup
230 
231 .seealso: MatFDColoringCreate(), MatFDColoringDestroy()
232 @*/
233 PetscErrorCode MatFDColoringSetUp(Mat mat,ISColoring iscoloring,MatFDColoring color)
234 {
235   PetscErrorCode ierr;
236 
237   PetscFunctionBegin;
238   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
239   PetscValidHeaderSpecific(color,MAT_FDCOLORING_CLASSID,3);
240   if (color->setupcalled) PetscFunctionReturn(0);
241 
242   ierr = PetscLogEventBegin(MAT_FDColoringSetUp,mat,0,0,0);CHKERRQ(ierr);
243   if (mat->ops->fdcoloringsetup) {
244     ierr = (*mat->ops->fdcoloringsetup)(mat,iscoloring,color);CHKERRQ(ierr);
245   } else SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
246 
247   color->setupcalled = PETSC_TRUE;
248    ierr   = PetscLogEventEnd(MAT_FDColoringSetUp,mat,0,0,0);CHKERRQ(ierr);
249   PetscFunctionReturn(0);
250 }
251 
252 /*@C
253    MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.
254 
255    Not Collective
256 
257    Input Parameters:
258 .  coloring - the coloring context
259 
260    Output Parameters:
261 +  f - the function
262 -  fctx - the optional user-defined function context
263 
264    Level: intermediate
265 
266 .keywords: Mat, Jacobian, finite differences, set, function
267 
268 .seealso: MatFDColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
269 
270 @*/
271 PetscErrorCode  MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
272 {
273   PetscFunctionBegin;
274   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
275   if (f) *f = matfd->f;
276   if (fctx) *fctx = matfd->fctx;
277   PetscFunctionReturn(0);
278 }
279 
280 /*@C
281    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
282 
283    Logically Collective on MatFDColoring
284 
285    Input Parameters:
286 +  coloring - the coloring context
287 .  f - the function
288 -  fctx - the optional user-defined function context
289 
290    Calling sequence of (*f) function:
291     For SNES:    PetscErrorCode (*f)(SNES,Vec,Vec,void*)
292     If not using SNES: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored
293 
294    Level: advanced
295 
296    Notes:
297     This function is usually used automatically by SNES (when one uses SNESSetJacobian() with the argument
298      SNESComputeJacobianDefaultColor()) and only needs to be used by someone computing a matrix via coloring directly by
299      calling MatFDColoringApply()
300 
301    Fortran Notes:
302     In Fortran you must call MatFDColoringSetFunction() for a coloring object to
303   be used without SNES or within the SNES solvers.
304 
305 .keywords: Mat, Jacobian, finite differences, set, function
306 
307 .seealso: MatFDColoringCreate(), MatFDColoringGetFunction(), MatFDColoringSetFromOptions()
308 
309 @*/
310 PetscErrorCode  MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
311 {
312   PetscFunctionBegin;
313   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
314   matfd->f    = f;
315   matfd->fctx = fctx;
316   PetscFunctionReturn(0);
317 }
318 
319 /*@
320    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
321    the options database.
322 
323    Collective on MatFDColoring
324 
325    The Jacobian, F'(u), is estimated with the differencing approximation
326 .vb
327        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
328        h = error_rel*u[i]                 if  abs(u[i]) > umin
329          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
330        dx_{i} = (0, ... 1, .... 0)
331 .ve
332 
333    Input Parameter:
334 .  coloring - the coloring context
335 
336    Options Database Keys:
337 +  -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function)
338 .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
339 .  -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
340 .  -mat_fd_coloring_view - Activates basic viewing
341 .  -mat_fd_coloring_view ::ascii_info - Activates viewing info
342 -  -mat_fd_coloring_view draw - Activates drawing
343 
344     Level: intermediate
345 
346 .keywords: Mat, finite differences, parameters
347 
348 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
349 
350 @*/
351 PetscErrorCode  MatFDColoringSetFromOptions(MatFDColoring matfd)
352 {
353   PetscErrorCode ierr;
354   PetscBool      flg;
355   char           value[3];
356 
357   PetscFunctionBegin;
358   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
359 
360   ierr = PetscObjectOptionsBegin((PetscObject)matfd);CHKERRQ(ierr);
361   ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
362   ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
363   ierr = PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,3,&flg);CHKERRQ(ierr);
364   if (flg) {
365     if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
366     else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
367     else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
368   }
369   ierr = PetscOptionsInt("-mat_fd_coloring_brows","Number of block rows","MatFDColoringSetBlockSize",matfd->brows,&matfd->brows,NULL);CHKERRQ(ierr);
370   ierr = PetscOptionsInt("-mat_fd_coloring_bcols","Number of block columns","MatFDColoringSetBlockSize",matfd->bcols,&matfd->bcols,&flg);CHKERRQ(ierr);
371   if (flg && matfd->bcols > matfd->ncolors) {
372     /* input bcols cannot be > matfd->ncolors, thus set it as ncolors */
373     matfd->bcols = matfd->ncolors;
374   }
375 
376   /* process any options handlers added with PetscObjectAddOptionsHandler() */
377   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)matfd);CHKERRQ(ierr);
378   PetscOptionsEnd();CHKERRQ(ierr);
379   PetscFunctionReturn(0);
380 }
381 
382 /*@C
383    MatFDColoringSetType - Sets the approach for computing the finite difference parameter
384 
385    Collective on MatFDColoring
386 
387    Input Parameters:
388 +  coloring - the coloring context
389 -  type - either MATMFFD_WP or MATMFFD_DS
390 
391    Options Database Keys:
392 .  -mat_fd_type - "wp" or "ds"
393 
394    Note: It is goofy that the argument type is MatMFFDType since the MatFDColoring actually computes the matrix entries
395          but the process of computing the entries is the same as as with the MatMFFD operation so we should reuse the names instead of
396          introducing another one.
397 
398    Level: intermediate
399 
400 .keywords: Mat, finite differences, parameters
401 
402 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
403 
404 @*/
405 PetscErrorCode  MatFDColoringSetType(MatFDColoring matfd,MatMFFDType type)
406 {
407   PetscFunctionBegin;
408   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
409   /*
410      It is goofy to handle the strings this way but currently there is no code to free a dynamically created matfd->htype
411      and this function is being provided as patch for a release so it shouldn't change the implementaton
412   */
413   if (type[0] == 'w' && type[1] == 'p') matfd->htype = "wp";
414   else if (type[0] == 'd' && type[1] == 's') matfd->htype = "ds";
415   else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",type);
416   PetscFunctionReturn(0);
417 }
418 
419 PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd,const char prefix[],const char optionname[])
420 {
421   PetscErrorCode    ierr;
422   PetscBool         flg;
423   PetscViewer       viewer;
424   PetscViewerFormat format;
425 
426   PetscFunctionBegin;
427   if (prefix) {
428     ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr);
429   } else {
430     ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd),((PetscObject)fd)->prefix,optionname,&viewer,&format,&flg);CHKERRQ(ierr);
431   }
432   if (flg) {
433     ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr);
434     ierr = MatFDColoringView(fd,viewer);CHKERRQ(ierr);
435     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
436     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
437   }
438   PetscFunctionReturn(0);
439 }
440 
441 /*@
442    MatFDColoringCreate - Creates a matrix coloring context for finite difference
443    computation of Jacobians.
444 
445    Collective on Mat
446 
447    Input Parameters:
448 +  mat - the matrix containing the nonzero structure of the Jacobian
449 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
450 
451     Output Parameter:
452 .   color - the new coloring context
453 
454     Level: intermediate
455 
456 .seealso: MatFDColoringDestroy(),SNESComputeJacobianDefaultColor(), ISColoringCreate(),
457           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
458           MatFDColoringView(), MatFDColoringSetParameters(), MatColoringCreate(), DMCreateColoring()
459 @*/
460 PetscErrorCode  MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
461 {
462   MatFDColoring  c;
463   MPI_Comm       comm;
464   PetscErrorCode ierr;
465   PetscInt       M,N;
466 
467   PetscFunctionBegin;
468   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
469   if (!mat->assembled) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Matrix must be assembled by calls to MatAssemblyBegin/End();");
470   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
471   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
472   if (M != N) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Only for square matrices");
473   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
474   ierr = PetscHeaderCreate(c,MAT_FDCOLORING_CLASSID,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr);
475 
476   c->ctype = iscoloring->ctype;
477 
478   if (mat->ops->fdcoloringcreate) {
479     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
480   } else SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
481 
482   ierr = MatCreateVecs(mat,NULL,&c->w1);CHKERRQ(ierr);
483   ierr = PetscLogObjectParent((PetscObject)c,(PetscObject)c->w1);CHKERRQ(ierr);
484   ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr);
485   ierr = PetscLogObjectParent((PetscObject)c,(PetscObject)c->w2);CHKERRQ(ierr);
486 
487   c->error_rel    = PETSC_SQRT_MACHINE_EPSILON;
488   c->umin         = 100.0*PETSC_SQRT_MACHINE_EPSILON;
489   c->currentcolor = -1;
490   c->htype        = "wp";
491   c->fset         = PETSC_FALSE;
492   c->setupcalled  = PETSC_FALSE;
493 
494   *color = c;
495   ierr   = PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);CHKERRQ(ierr);
496   ierr   = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
497   PetscFunctionReturn(0);
498 }
499 
500 /*@
501     MatFDColoringDestroy - Destroys a matrix coloring context that was created
502     via MatFDColoringCreate().
503 
504     Collective on MatFDColoring
505 
506     Input Parameter:
507 .   c - coloring context
508 
509     Level: intermediate
510 
511 .seealso: MatFDColoringCreate()
512 @*/
513 PetscErrorCode  MatFDColoringDestroy(MatFDColoring *c)
514 {
515   PetscErrorCode ierr;
516   PetscInt       i;
517   MatFDColoring  color = *c;
518 
519   PetscFunctionBegin;
520   if (!*c) PetscFunctionReturn(0);
521   if (--((PetscObject)color)->refct > 0) {*c = 0; PetscFunctionReturn(0);}
522 
523   for (i=0; i<color->ncolors; i++) {
524     ierr = PetscFree(color->columns[i]);CHKERRQ(ierr);
525   }
526   ierr = PetscFree(color->ncolumns);CHKERRQ(ierr);
527   ierr = PetscFree(color->columns);CHKERRQ(ierr);
528   ierr = PetscFree(color->nrows);CHKERRQ(ierr);
529   if (color->htype[0] == 'w') {
530     ierr = PetscFree(color->matentry2);CHKERRQ(ierr);
531   } else {
532     ierr = PetscFree(color->matentry);CHKERRQ(ierr);
533   }
534   ierr = PetscFree(color->dy);CHKERRQ(ierr);
535   if (color->vscale) {ierr = VecDestroy(&color->vscale);CHKERRQ(ierr);}
536   ierr = VecDestroy(&color->w1);CHKERRQ(ierr);
537   ierr = VecDestroy(&color->w2);CHKERRQ(ierr);
538   ierr = VecDestroy(&color->w3);CHKERRQ(ierr);
539   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
540   PetscFunctionReturn(0);
541 }
542 
543 /*@C
544     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
545       that are currently being perturbed.
546 
547     Not Collective
548 
549     Input Parameters:
550 .   coloring - coloring context created with MatFDColoringCreate()
551 
552     Output Parameters:
553 +   n - the number of local columns being perturbed
554 -   cols - the column indices, in global numbering
555 
556    Level: advanced
557 
558    Fortran Note:
559    This routine has a different interface for Fortran
560 $     #include <petsc/finclude/petscmat.h>
561 $          use petscmat
562 $          PetscInt, pointer :: array(:)
563 $          PetscErrorCode  ierr
564 $          MatFDColoring   i
565 $          call MatFDColoringGetPerturbedColumnsF90(i,array,ierr)
566 $      use the entries of array ...
567 $          call MatFDColoringRestorePerturbedColumnsF90(i,array,ierr)
568 
569 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()
570 
571 .keywords: coloring, Jacobian, finite differences
572 @*/
573 PetscErrorCode  MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,const PetscInt *cols[])
574 {
575   PetscFunctionBegin;
576   if (coloring->currentcolor >= 0) {
577     *n    = coloring->ncolumns[coloring->currentcolor];
578     *cols = coloring->columns[coloring->currentcolor];
579   } else {
580     *n = 0;
581   }
582   PetscFunctionReturn(0);
583 }
584 
585 /*@
586     MatFDColoringApply - Given a matrix for which a MatFDColoring context
587     has been created, computes the Jacobian for a function via finite differences.
588 
589     Collective on MatFDColoring
590 
591     Input Parameters:
592 +   mat - location to store Jacobian
593 .   coloring - coloring context created with MatFDColoringCreate()
594 .   x1 - location at which Jacobian is to be computed
595 -   sctx - context required by function, if this is being used with the SNES solver then it is SNES object, otherwise it is null
596 
597     Options Database Keys:
598 +    -mat_fd_type - "wp" or "ds"  (see MATMFFD_WP or MATMFFD_DS)
599 .    -mat_fd_coloring_view - Activates basic viewing or coloring
600 .    -mat_fd_coloring_view draw - Activates drawing of coloring
601 -    -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info
602 
603     Level: intermediate
604 
605 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction()
606 
607 .keywords: coloring, Jacobian, finite differences
608 @*/
609 PetscErrorCode  MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,void *sctx)
610 {
611   PetscErrorCode ierr;
612   PetscBool      flg = PETSC_FALSE;
613 
614   PetscFunctionBegin;
615   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
616   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
617   PetscValidHeaderSpecific(x1,VEC_CLASSID,3);
618   if (!coloring->f) SETERRQ(PetscObjectComm((PetscObject)J),PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
619   if (!J->ops->fdcoloringapply) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)J)->type_name);
620   if (!coloring->setupcalled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetUp()");
621 
622   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
623   ierr = PetscOptionsGetBool(((PetscObject)coloring)->options,NULL,"-mat_fd_coloring_dont_rezero",&flg,NULL);CHKERRQ(ierr);
624   if (flg) {
625     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
626   } else {
627     PetscBool assembled;
628     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
629     if (assembled) {
630       ierr = MatZeroEntries(J);CHKERRQ(ierr);
631     }
632   }
633 
634   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
635   ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,sctx);CHKERRQ(ierr);
636   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
637   if (!coloring->viewed) {
638     ierr = MatFDColoringViewFromOptions(coloring,NULL,"-mat_fd_coloring_view");CHKERRQ(ierr);
639     coloring->viewed = PETSC_TRUE;
640   }
641   PetscFunctionReturn(0);
642 }
643