xref: /petsc/src/mat/matfd/fdmatrix.c (revision 54d96fa383ba80e0a45dd9f0fcec1909a0522f96)
1 /*$Id: fdmatrix.c,v 1.62 2000/05/13 04:18:00 bsmith Exp bsmith $*/
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 "petsc.h"
9 #include "src/mat/matimpl.h"        /*I "petscmat.h" I*/
10 #include "src/vec/vecimpl.h"
11 
12 #undef __FUNC__
13 #define __FUNC__ /*<a name="MatFDColoringView_Draw_Zoom"></a>*/"MatFDColoringView_Draw_Zoom"
14 static int MatFDColoringView_Draw_Zoom(Draw draw,void *Aa)
15 {
16   MatFDColoring fd = (MatFDColoring)Aa;
17   int           ierr,i,j;
18   PetscReal     x,y;
19 
20   PetscFunctionBegin;
21 
22   /* loop over colors  */
23   for (i=0; i<fd->ncolors; i++) {
24     for (j=0; j<fd->nrows[i]; j++) {
25       y = fd->M - fd->rows[i][j] - fd->rstart;
26       x = fd->columnsforrow[i][j];
27       ierr = DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
28     }
29   }
30   PetscFunctionReturn(0);
31 }
32 
33 #undef __FUNC__
34 #define __FUNC__ /*<a name="MatFDColoringView_Draw"></a>*/"MatFDColoringView_Draw"
35 static int MatFDColoringView_Draw(MatFDColoring fd,Viewer viewer)
36 {
37   int         ierr;
38   PetscTruth  isnull;
39   Draw        draw;
40   PetscReal   xr,yr,xl,yl,h,w;
41 
42   PetscFunctionBegin;
43   ierr = ViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
44   ierr = DrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
45 
46   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
47 
48   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
49   xr += w;     yr += h;    xl = -w;     yl = -h;
50   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
51   ierr = DrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
52   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
53   PetscFunctionReturn(0);
54 }
55 
56 #undef __FUNC__
57 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringView"
58 /*@C
59    MatFDColoringView - Views a finite difference coloring context.
60 
61    Collective on MatFDColoring
62 
63    Input  Parameters:
64 +  c - the coloring context
65 -  viewer - visualization context
66 
67    Level: intermediate
68 
69    Notes:
70    The available visualization contexts include
71 +     VIEWER_STDOUT_SELF - standard output (default)
72 .     VIEWER_STDOUT_WORLD - synchronized standard
73         output where only the first processor opens
74         the file.  All other processors send their
75         data to the first processor to print.
76 -     VIEWER_DRAW_WORLD - graphical display of nonzero structure
77 
78    Notes:
79      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
80    involves moe than 33 then some seemingly identical colors are displayed making it look
81    like an illegal coloring. This is just a graphical artifact.
82 
83 .seealso: MatFDColoringCreate()
84 
85 .keywords: Mat, finite differences, coloring, view
86 @*/
87 int MatFDColoringView(MatFDColoring c,Viewer viewer)
88 {
89   int        i,j,format,ierr;
90   PetscTruth isdraw,isascii;
91 
92   PetscFunctionBegin;
93   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
94   if (!viewer) viewer = VIEWER_STDOUT_(c->comm);
95   PetscValidHeaderSpecific(viewer,VIEWER_COOKIE);
96   PetscCheckSameComm(c,viewer);
97 
98   ierr  = PetscTypeCompare((PetscObject)viewer,DRAW_VIEWER,&isdraw);CHKERRQ(ierr);
99   ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr);
100   if (isdraw) {
101     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
102   } else if (isascii) {
103     ierr = ViewerASCIIPrintf(viewer,"MatFDColoring Object:\n");CHKERRQ(ierr);
104     ierr = ViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",c->error_rel);CHKERRQ(ierr);
105     ierr = ViewerASCIIPrintf(viewer,"  Umin=%g\n",c->umin);CHKERRQ(ierr);
106     ierr = ViewerASCIIPrintf(viewer,"  Number of colors=%d\n",c->ncolors);CHKERRQ(ierr);
107 
108     ierr = ViewerGetFormat(viewer,&format);CHKERRQ(ierr);
109     if (format != VIEWER_FORMAT_ASCII_INFO) {
110       for (i=0; i<c->ncolors; i++) {
111         ierr = ViewerASCIIPrintf(viewer,"  Information for color %d\n",i);CHKERRQ(ierr);
112         ierr = ViewerASCIIPrintf(viewer,"    Number of columns %d\n",c->ncolumns[i]);CHKERRQ(ierr);
113         for (j=0; j<c->ncolumns[i]; j++) {
114           ierr = ViewerASCIIPrintf(viewer,"      %d\n",c->columns[i][j]);CHKERRQ(ierr);
115         }
116         ierr = ViewerASCIIPrintf(viewer,"    Number of rows %d\n",c->nrows[i]);CHKERRQ(ierr);
117         for (j=0; j<c->nrows[i]; j++) {
118           ierr = ViewerASCIIPrintf(viewer,"      %d %d \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
119         }
120       }
121     }
122     ierr = ViewerFlush(viewer);CHKERRQ(ierr);
123   } else {
124     SETERRQ1(1,1,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
125   }
126   PetscFunctionReturn(0);
127 }
128 
129 #undef __FUNC__
130 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringSetParameters"
131 /*@
132    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
133    a Jacobian matrix using finite differences.
134 
135    Collective on MatFDColoring
136 
137    The Jacobian is estimated with the differencing approximation
138 .vb
139        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
140        h = error_rel*u[i]                 if  abs(u[i]) > umin
141          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
142        dx_{i} = (0, ... 1, .... 0)
143 .ve
144 
145    Input Parameters:
146 +  coloring - the coloring context
147 .  error_rel - relative error
148 -  umin - minimum allowable u-value magnitude
149 
150    Level: advanced
151 
152 .keywords: Mat, finite differences, coloring, set, parameters
153 
154 .seealso: MatFDColoringCreate()
155 @*/
156 int MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
157 {
158   PetscFunctionBegin;
159   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
160 
161   if (error != PETSC_DEFAULT) matfd->error_rel = error;
162   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
163   PetscFunctionReturn(0);
164 }
165 
166 #undef __FUNC__
167 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringSetFrequency"
168 /*@
169    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
170    matrices.
171 
172    Collective on MatFDColoring
173 
174    Input Parameters:
175 +  coloring - the coloring context
176 -  freq - frequency (default is 1)
177 
178    Options Database Keys:
179 .  -mat_fd_coloring_freq <freq>  - Sets coloring frequency
180 
181    Level: advanced
182 
183    Notes:
184    Using a modified Newton strategy, where the Jacobian remains fixed for several
185    iterations, can be cost effective in terms of overall nonlinear solution
186    efficiency.  This parameter indicates that a new Jacobian will be computed every
187    <freq> nonlinear iterations.
188 
189 .keywords: Mat, finite differences, coloring, set, frequency
190 
191 .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency()
192 @*/
193 int MatFDColoringSetFrequency(MatFDColoring matfd,int freq)
194 {
195   PetscFunctionBegin;
196   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
197 
198   matfd->freq = freq;
199   PetscFunctionReturn(0);
200 }
201 
202 #undef __FUNC__
203 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringGetFrequency"
204 /*@
205    MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian
206    matrices.
207 
208    Not Collective
209 
210    Input Parameters:
211 .  coloring - the coloring context
212 
213    Output Parameters:
214 .  freq - frequency (default is 1)
215 
216    Options Database Keys:
217 .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
218 
219    Level: advanced
220 
221    Notes:
222    Using a modified Newton strategy, where the Jacobian remains fixed for several
223    iterations, can be cost effective in terms of overall nonlinear solution
224    efficiency.  This parameter indicates that a new Jacobian will be computed every
225    <freq> nonlinear iterations.
226 
227 .keywords: Mat, finite differences, coloring, get, frequency
228 
229 .seealso: MatFDColoringSetFrequency()
230 @*/
231 int MatFDColoringGetFrequency(MatFDColoring matfd,int *freq)
232 {
233   PetscFunctionBegin;
234   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
235 
236   *freq = matfd->freq;
237   PetscFunctionReturn(0);
238 }
239 
240 #undef __FUNC__
241 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringSetFunction"
242 /*@C
243    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
244 
245    Collective on MatFDColoring
246 
247    Input Parameters:
248 +  coloring - the coloring context
249 .  f - the function
250 -  fctx - the optional user-defined function context
251 
252    Level: intermediate
253 
254    Notes:
255     In Fortran you must call MatFDColoringSetFunctionSNES() for a coloring object to
256   be used with the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used
257   with the TS solvers.
258 
259 .keywords: Mat, Jacobian, finite differences, set, function
260 @*/
261 int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void),void *fctx)
262 {
263   PetscFunctionBegin;
264   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
265 
266   matfd->f    = f;
267   matfd->fctx = fctx;
268 
269   PetscFunctionReturn(0);
270 }
271 
272 #undef __FUNC__
273 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringSetFromOptions"
274 /*@
275    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
276    the options database.
277 
278    Collective on MatFDColoring
279 
280    The Jacobian, F'(u), is estimated with the differencing approximation
281 .vb
282        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
283        h = error_rel*u[i]                 if  abs(u[i]) > umin
284          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
285        dx_{i} = (0, ... 1, .... 0)
286 .ve
287 
288    Input Parameter:
289 .  coloring - the coloring context
290 
291    Options Database Keys:
292 +  -mat_fd_coloring_error <err> - Sets <err> (square root
293            of relative error in the function)
294 .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
295 .  -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian
296 .  -mat_fd_coloring_view - Activates basic viewing
297 .  -mat_fd_coloring_view_info - Activates viewing info
298 -  -mat_fd_coloring_view_draw - Activates drawing
299 
300     Level: intermediate
301 
302 .keywords: Mat, finite differences, parameters
303 @*/
304 int MatFDColoringSetFromOptions(MatFDColoring matfd)
305 {
306   int        ierr,freq = 1;
307   PetscReal  error = PETSC_DEFAULT,umin = PETSC_DEFAULT;
308   PetscTruth flag;
309 
310   PetscFunctionBegin;
311   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
312 
313   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,PETSC_NULL);CHKERRQ(ierr);
314   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,PETSC_NULL);CHKERRQ(ierr);
315   ierr = MatFDColoringSetParameters(matfd,error,umin);CHKERRQ(ierr);
316   ierr = OptionsGetInt(matfd->prefix,"-mat_fd_coloring_freq",&freq,PETSC_NULL);CHKERRQ(ierr);
317   ierr = MatFDColoringSetFrequency(matfd,freq);CHKERRQ(ierr);
318   ierr = OptionsHasName(PETSC_NULL,"-help",&flag);CHKERRQ(ierr);
319   if (flag) {
320     ierr = MatFDColoringPrintHelp(matfd);CHKERRQ(ierr);
321   }
322   PetscFunctionReturn(0);
323 }
324 
325 #undef __FUNC__
326 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringPrintHelp"
327 /*@
328     MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations
329     using coloring.
330 
331     Collective on MatFDColoring
332 
333     Input Parameter:
334 .   fdcoloring - the MatFDColoring context
335 
336     Level: intermediate
337 
338 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions()
339 @*/
340 int MatFDColoringPrintHelp(MatFDColoring fd)
341 {
342   int ierr;
343 
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE);
346 
347   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_err <err>: set sqrt rel tol in function, defaults to %g\n",fd->error_rel);CHKERRQ(ierr);
348   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_umin <umin>: see users manual, defaults to %d\n",fd->umin);CHKERRQ(ierr);
349   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_freq <freq>: frequency that Jacobian is recomputed, defaults to %d\n",fd->freq);CHKERRQ(ierr);
350   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view\n");CHKERRQ(ierr);
351   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_draw\n");CHKERRQ(ierr);
352   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_info\n");CHKERRQ(ierr);
353   PetscFunctionReturn(0);
354 }
355 
356 #undef __FUNC__
357 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringView_Private"
358 int MatFDColoringView_Private(MatFDColoring fd)
359 {
360   int        ierr;
361   PetscTruth flg;
362 
363   PetscFunctionBegin;
364   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr);
365   if (flg) {
366     ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
367   }
368   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr);
369   if (flg) {
370     ierr = ViewerPushFormat(VIEWER_STDOUT_(fd->comm),VIEWER_FORMAT_ASCII_INFO,PETSC_NULL);CHKERRQ(ierr);
371     ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
372     ierr = ViewerPopFormat(VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
373   }
374   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr);
375   if (flg) {
376     ierr = MatFDColoringView(fd,VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
377     ierr = ViewerFlush(VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
378   }
379   PetscFunctionReturn(0);
380 }
381 
382 #undef __FUNC__
383 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringCreate"
384 /*@C
385    MatFDColoringCreate - Creates a matrix coloring context for finite difference
386    computation of Jacobians.
387 
388    Collective on Mat
389 
390    Input Parameters:
391 +  mat - the matrix containing the nonzero structure of the Jacobian
392 -  iscoloring - the coloring of the matrix
393 
394     Output Parameter:
395 .   color - the new coloring context
396 
397     Options Database Keys:
398 +    -mat_fd_coloring_view - Activates basic viewing or coloring
399 .    -mat_fd_coloring_view_draw - Activates drawing of coloring
400 -    -mat_fd_coloring_view_info - Activates viewing of coloring info
401 
402     Level: intermediate
403 
404 .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
405           MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
406 @*/
407 int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
408 {
409   MatFDColoring c;
410   MPI_Comm      comm;
411   int           ierr,M,N;
412 
413   PetscFunctionBegin;
414   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
415   if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Only for square matrices");
416 
417   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
418   PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView);
419   PLogObjectCreate(c);
420 
421   if (mat->ops->fdcoloringcreate) {
422     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
423   } else {
424     SETERRQ(PETSC_ERR_SUP,0,"Code not yet written for this matrix type");
425   }
426 
427   c->error_rel = 1.e-8;
428   c->umin      = 1.e-6;
429   c->freq      = 1;
430 
431   ierr = MatFDColoringView_Private(c);CHKERRQ(ierr);
432 
433   *color = c;
434 
435   PetscFunctionReturn(0);
436 }
437 
438 #undef __FUNC__
439 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringDestroy"
440 /*@C
441     MatFDColoringDestroy - Destroys a matrix coloring context that was created
442     via MatFDColoringCreate().
443 
444     Collective on MatFDColoring
445 
446     Input Parameter:
447 .   c - coloring context
448 
449     Level: intermediate
450 
451 .seealso: MatFDColoringCreate()
452 @*/
453 int MatFDColoringDestroy(MatFDColoring c)
454 {
455   int i,ierr;
456 
457   PetscFunctionBegin;
458   if (--c->refct > 0) PetscFunctionReturn(0);
459 
460 
461   for (i=0; i<c->ncolors; i++) {
462     if (c->columns[i])       {ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);}
463     if (c->rows[i])          {ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);}
464     if (c->columnsforrow[i]) {ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);}
465   }
466   ierr = PetscFree(c->ncolumns);CHKERRQ(ierr);
467   ierr = PetscFree(c->columns);CHKERRQ(ierr);
468   ierr = PetscFree(c->nrows);CHKERRQ(ierr);
469   ierr = PetscFree(c->rows);CHKERRQ(ierr);
470   ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr);
471   ierr = PetscFree(c->scale);CHKERRQ(ierr);
472   if (c->w1) {
473     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
474     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
475     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
476   }
477   PLogObjectDestroy(c);
478   PetscHeaderDestroy(c);
479   PetscFunctionReturn(0);
480 }
481 
482 
483 #undef __FUNC__
484 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringApply"
485 /*@
486     MatFDColoringApply - Given a matrix for which a MatFDColoring context
487     has been created, computes the Jacobian for a function via finite differences.
488 
489     Collective on MatFDColoring
490 
491     Input Parameters:
492 +   mat - location to store Jacobian
493 .   coloring - coloring context created with MatFDColoringCreate()
494 .   x1 - location at which Jacobian is to be computed
495 -   sctx - optional context required by function (actually a SNES context)
496 
497    Options Database Keys:
498 .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
499 
500    Level: intermediate
501 
502 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
503 
504 .keywords: coloring, Jacobian, finite differences
505 @*/
506 int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
507 {
508   int           k,ierr,N,start,end,l,row,col,srow;
509   Scalar        dx,mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale,*w3_array;
510   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
511   MPI_Comm      comm = coloring->comm;
512   Vec           w1,w2,w3;
513   int           (*f)(void *,Vec,Vec,void*)= (int (*)(void *,Vec,Vec,void *))coloring->f;
514   void          *fctx = coloring->fctx;
515   PetscTruth    flg;
516 
517   PetscFunctionBegin;
518   PetscValidHeaderSpecific(J,MAT_COOKIE);
519   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
520   PetscValidHeaderSpecific(x1,VEC_COOKIE);
521 
522 
523   if (!coloring->w1) {
524     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
525     PLogObjectParent(coloring,coloring->w1);
526     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
527     PLogObjectParent(coloring,coloring->w2);
528     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
529     PLogObjectParent(coloring,coloring->w3);
530   }
531   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
532 
533   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
534   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
535   if (flg) {
536     PLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
537   } else {
538     ierr = MatZeroEntries(J);CHKERRQ(ierr);
539   }
540 
541   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
542   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
543   ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
544 
545   ierr = PetscMemzero(wscale,N*sizeof(Scalar));CHKERRQ(ierr);
546   /*
547       Loop over each color
548   */
549 
550   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);
551   for (k=0; k<coloring->ncolors; k++) {
552     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);
553     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
554     /*
555        Loop over each column associated with color adding the
556        perturbation to the vector w3.
557     */
558     for (l=0; l<coloring->ncolumns[k]; l++) {
559       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
560       dx  = xx[col-start];
561       if (dx == 0.0) dx = 1.0;
562 #if !defined(PETSC_USE_COMPLEX)
563       if (dx < umin && dx >= 0.0)      dx = umin;
564       else if (dx < 0.0 && dx > -umin) dx = -umin;
565 #else
566       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
567       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
568 #endif
569       dx                    *= epsilon;
570       wscale[col]            = 1.0/dx;
571       w3_array[col - start] += dx;
572     }
573     ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
574 
575     /*
576        Evaluate function at x1 + dx (here dx is a vector of perturbations)
577     */
578     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
579     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
580     /* Communicate scale to all processors */
581     ierr = MPI_Allreduce(wscale,scale,N,MPIU_SCALAR,PetscSum_Op,comm);CHKERRQ(ierr);
582     /*
583        Loop over rows of vector, putting results into Jacobian matrix
584     */
585     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
586     for (l=0; l<coloring->nrows[k]; l++) {
587       row    = coloring->rows[k][l];
588       col    = coloring->columnsforrow[k][l];
589       y[row] *= scale[col];
590       srow   = row + start;
591       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
592     }
593     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
594   }
595   ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
596   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
597   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
598   PetscFunctionReturn(0);
599 }
600 
601 #undef __FUNC__
602 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringApplyTS"
603 /*@
604     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
605     has been created, computes the Jacobian for a function via finite differences.
606 
607    Collective on Mat, MatFDColoring, and Vec
608 
609     Input Parameters:
610 +   mat - location to store Jacobian
611 .   coloring - coloring context created with MatFDColoringCreate()
612 .   x1 - location at which Jacobian is to be computed
613 -   sctx - optional context required by function (actually a SNES context)
614 
615    Options Database Keys:
616 .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
617 
618    Level: intermediate
619 
620 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
621 
622 .keywords: coloring, Jacobian, finite differences
623 @*/
624 int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
625 {
626   int           k,ierr,N,start,end,l,row,col,srow;
627   int           (*f)(void *,PetscReal,Vec,Vec,void*)= (int (*)(void *,PetscReal,Vec,Vec,void *))coloring->f;
628   Scalar        dx,mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale;
629   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
630   MPI_Comm      comm = coloring->comm;
631   Vec           w1,w2,w3;
632   void          *fctx = coloring->fctx;
633   PetscTruth    flg;
634 
635   PetscFunctionBegin;
636   PetscValidHeaderSpecific(J,MAT_COOKIE);
637   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
638   PetscValidHeaderSpecific(x1,VEC_COOKIE);
639 
640   if (!coloring->w1) {
641     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
642     PLogObjectParent(coloring,coloring->w1);
643     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
644     PLogObjectParent(coloring,coloring->w2);
645     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
646     PLogObjectParent(coloring,coloring->w3);
647   }
648   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
649 
650   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
651   if (flg) {
652     PLogInfo(coloring,"MatFDColoringApplyTS: Not calling MatZeroEntries()\n");
653   } else {
654     ierr = MatZeroEntries(J);CHKERRQ(ierr);
655   }
656 
657   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
658   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
659   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
660 
661   ierr = PetscMemzero(wscale,N*sizeof(Scalar));CHKERRQ(ierr);
662   /*
663       Loop over each color
664   */
665 
666   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);
667   for (k=0; k<coloring->ncolors; k++) {
668     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
669     /*
670        Loop over each column associated with color adding the
671        perturbation to the vector w3.
672     */
673     for (l=0; l<coloring->ncolumns[k]; l++) {
674       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
675       dx  = xx[col-start];
676       if (dx == 0.0) dx = 1.0;
677 #if !defined(PETSC_USE_COMPLEX)
678       if (dx < umin && dx >= 0.0)      dx = umin;
679       else if (dx < 0.0 && dx > -umin) dx = -umin;
680 #else
681       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
682       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
683 #endif
684       dx          *= epsilon;
685       wscale[col] = 1.0/dx;
686       ierr = VecSetValues(w3,1,&col,&dx,ADD_VALUES);CHKERRQ(ierr);
687     }
688     /*
689        Evaluate function at x1 + dx (here dx is a vector of perturbations)
690     */
691     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
692     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
693     /* Communicate scale to all processors */
694     ierr = MPI_Allreduce(wscale,scale,N,MPIU_SCALAR,PetscSum_Op,comm);CHKERRQ(ierr);
695     /*
696        Loop over rows of vector, putting results into Jacobian matrix
697     */
698     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
699     for (l=0; l<coloring->nrows[k]; l++) {
700       row    = coloring->rows[k][l];
701       col    = coloring->columnsforrow[k][l];
702       y[row] *= scale[col];
703       srow   = row + start;
704       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
705     }
706     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
707   }
708   ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
709   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
710   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
711   PetscFunctionReturn(0);
712 }
713 
714 
715 
716