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