xref: /petsc/src/mat/matfd/fdmatrix.c (revision 00ff320a6701aa587ed3bd591b944da12a89b695)
1 /*$Id: fdmatrix.c,v 1.72 2000/08/01 20:02:45 bsmith Exp balay $*/
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,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()
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,freq = 1;
306   PetscReal  error = PETSC_DEFAULT,umin = PETSC_DEFAULT;
307   PetscTruth flag;
308 
309   PetscFunctionBegin;
310   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
311 
312   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,PETSC_NULL);CHKERRQ(ierr);
313   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,PETSC_NULL);CHKERRQ(ierr);
314   ierr = MatFDColoringSetParameters(matfd,error,umin);CHKERRQ(ierr);
315   ierr = OptionsGetInt(matfd->prefix,"-mat_fd_coloring_freq",&freq,PETSC_NULL);CHKERRQ(ierr);
316   ierr = MatFDColoringSetFrequency(matfd,freq);CHKERRQ(ierr);
317   ierr = OptionsHasName(PETSC_NULL,"-help",&flag);CHKERRQ(ierr);
318   if (flag) {
319     ierr = MatFDColoringPrintHelp(matfd);CHKERRQ(ierr);
320   }
321   PetscFunctionReturn(0);
322 }
323 
324 #undef __FUNC__
325 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringPrintHelp"
326 /*@
327     MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations
328     using coloring.
329 
330     Collective on MatFDColoring
331 
332     Input Parameter:
333 .   fdcoloring - the MatFDColoring context
334 
335     Level: intermediate
336 
337 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions()
338 @*/
339 int MatFDColoringPrintHelp(MatFDColoring fd)
340 {
341   int ierr;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE);
345 
346   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_err <err>: set sqrt rel tol in function, defaults to %g\n",fd->error_rel);CHKERRQ(ierr);
347   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_umin <umin>: see users manual, defaults to %d\n",fd->umin);CHKERRQ(ierr);
348   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_freq <freq>: frequency that Jacobian is recomputed, defaults to %d\n",fd->freq);CHKERRQ(ierr);
349   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view\n");CHKERRQ(ierr);
350   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_draw\n");CHKERRQ(ierr);
351   ierr = (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_info\n");CHKERRQ(ierr);
352   PetscFunctionReturn(0);
353 }
354 
355 #undef __FUNC__
356 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringView_Private"
357 int MatFDColoringView_Private(MatFDColoring fd)
358 {
359   int        ierr;
360   PetscTruth flg;
361 
362   PetscFunctionBegin;
363   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr);
364   if (flg) {
365     ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
366   }
367   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr);
368   if (flg) {
369     ierr = ViewerPushFormat(VIEWER_STDOUT_(fd->comm),VIEWER_FORMAT_ASCII_INFO,PETSC_NULL);CHKERRQ(ierr);
370     ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
371     ierr = ViewerPopFormat(VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
372   }
373   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr);
374   if (flg) {
375     ierr = MatFDColoringView(fd,VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
376     ierr = ViewerFlush(VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
377   }
378   PetscFunctionReturn(0);
379 }
380 
381 #undef __FUNC__
382 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringCreate"
383 /*@C
384    MatFDColoringCreate - Creates a matrix coloring context for finite difference
385    computation of Jacobians.
386 
387    Collective on Mat
388 
389    Input Parameters:
390 +  mat - the matrix containing the nonzero structure of the Jacobian
391 -  iscoloring - the coloring of the matrix
392 
393     Output Parameter:
394 .   color - the new coloring context
395 
396     Options Database Keys:
397 +    -mat_fd_coloring_view - Activates basic viewing or coloring
398 .    -mat_fd_coloring_view_draw - Activates drawing of coloring
399 -    -mat_fd_coloring_view_info - Activates viewing of coloring info
400 
401     Level: intermediate
402 
403 .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
404           MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
405 @*/
406 int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
407 {
408   MatFDColoring c;
409   MPI_Comm      comm;
410   int           ierr,M,N;
411 
412   PetscFunctionBegin;
413   PLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);
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   PLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);
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   for (i=0; i<c->ncolors; i++) {
461     if (c->columns[i])         {ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);}
462     if (c->rows[i])            {ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);}
463     if (c->columnsforrow[i])   {ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);}
464     if (c->vscaleforrow && c->vscaleforrow[i]) {ierr = PetscFree(c->vscaleforrow[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   if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);}
472   if (c->vscale)       {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);}
473   if (c->w1) {
474     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
475     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
476     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
477   }
478   PLogObjectDestroy(c);
479   PetscHeaderDestroy(c);
480   PetscFunctionReturn(0);
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           (*f)(void *,Vec,Vec,void*)= (int (*)(void *,Vec,Vec,void *))coloring->f;
509   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow;
510   Scalar        dx,mone = -1.0,*y,*xx,*w3_array;
511   Scalar        *vscale_array;
512   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
513   Vec           w1,w2,w3;
514   void          *fctx = coloring->fctx;
515   PetscTruth    flg;
516 
517 
518   PetscFunctionBegin;
519   PetscValidHeaderSpecific(J,MAT_COOKIE);
520   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
521   PetscValidHeaderSpecific(x1,VEC_COOKIE);
522 
523   PLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);
524   if (!coloring->w1) {
525     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
526     PLogObjectParent(coloring,coloring->w1);
527     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
528     PLogObjectParent(coloring,coloring->w2);
529     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
530     PLogObjectParent(coloring,coloring->w3);
531   }
532   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
533 
534   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
535   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
536   if (flg) {
537     PLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
538   } else {
539     ierr = MatZeroEntries(J);CHKERRQ(ierr);
540   }
541 
542   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
543   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
544   ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
545 
546   /*
547       Compute all the scale factors and share with other processors
548   */
549   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
550   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
551   for (k=0; k<coloring->ncolors; k++) {
552     /*
553        Loop over each column associated with color adding the
554        perturbation to the vector w3.
555     */
556     for (l=0; l<coloring->ncolumns[k]; l++) {
557       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
558       dx  = xx[col];
559       if (dx == 0.0) dx = 1.0;
560 #if !defined(PETSC_USE_COMPLEX)
561       if (dx < umin && dx >= 0.0)      dx = umin;
562       else if (dx < 0.0 && dx > -umin) dx = -umin;
563 #else
564       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
565       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
566 #endif
567       dx                *= epsilon;
568       vscale_array[col] = 1.0/dx;
569     }
570   }
571   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
572   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
573   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
574 
575   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
576   else                        vscaleforrow = coloring->columnsforrow;
577 
578   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
579   /*
580       Loop over each color
581   */
582   for (k=0; k<coloring->ncolors; k++) {
583     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
584     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
585     /*
586        Loop over each column associated with color adding the
587        perturbation to the vector w3.
588     */
589     for (l=0; l<coloring->ncolumns[k]; l++) {
590       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
591       dx  = xx[col];
592       if (dx == 0.0) dx = 1.0;
593 #if !defined(PETSC_USE_COMPLEX)
594       if (dx < umin && dx >= 0.0)      dx = umin;
595       else if (dx < 0.0 && dx > -umin) dx = -umin;
596 #else
597       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
598       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
599 #endif
600       dx            *= epsilon;
601       if (!PetscAbsScalar(dx)) SETERRQ(1,1,"Computed 0 differencing parameter");
602       w3_array[col] += dx;
603     }
604     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
605 
606     /*
607        Evaluate function at x1 + dx (here dx is a vector of perturbations)
608     */
609 
610     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
611     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
612 
613     /*
614        Loop over rows of vector, putting results into Jacobian matrix
615     */
616     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
617     for (l=0; l<coloring->nrows[k]; l++) {
618       row    = coloring->rows[k][l];
619       col    = coloring->columnsforrow[k][l];
620       y[row] *= vscale_array[vscaleforrow[k][l]];
621       srow   = row + start;
622       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
623     }
624     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
625   }
626   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
627   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
628   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
629   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
630   PLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);
631 
632   ierr = OptionsHasName(PETSC_NULL,"-mat_null_space_test",&flg);CHKERRQ(ierr);
633   if (flg) {
634     ierr = MatNullSpaceTest(J->nullsp,J);CHKERRQ(ierr);
635   }
636   PetscFunctionReturn(0);
637 }
638 
639 #undef __FUNC__
640 #define __FUNC__ /*<a name=""></a>*/"MatFDColoringApplyTS"
641 /*@
642     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
643     has been created, computes the Jacobian for a function via finite differences.
644 
645    Collective on Mat, MatFDColoring, and Vec
646 
647     Input Parameters:
648 +   mat - location to store Jacobian
649 .   coloring - coloring context created with MatFDColoringCreate()
650 .   x1 - location at which Jacobian is to be computed
651 -   sctx - optional context required by function (actually a SNES context)
652 
653    Options Database Keys:
654 .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
655 
656    Level: intermediate
657 
658 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
659 
660 .keywords: coloring, Jacobian, finite differences
661 @*/
662 int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
663 {
664   int           (*f)(void *,PetscReal,Vec,Vec,void*)=(int (*)(void *,PetscReal,Vec,Vec,void *))coloring->f;
665   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow;
666   Scalar        dx,mone = -1.0,*y,*xx,*w3_array;
667   Scalar        *vscale_array;
668   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
669   Vec           w1,w2,w3;
670   void          *fctx = coloring->fctx;
671   PetscTruth    flg;
672 
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(J,MAT_COOKIE);
675   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
676   PetscValidHeaderSpecific(x1,VEC_COOKIE);
677 
678   PLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);
679   if (!coloring->w1) {
680     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
681     PLogObjectParent(coloring,coloring->w1);
682     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
683     PLogObjectParent(coloring,coloring->w2);
684     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
685     PLogObjectParent(coloring,coloring->w3);
686   }
687   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
688 
689   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
690   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
691   if (flg) {
692     PLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
693   } else {
694     ierr = MatZeroEntries(J);CHKERRQ(ierr);
695   }
696 
697   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
698   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
699   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
700 
701   /*
702       Compute all the scale factors and share with other processors
703   */
704   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
705   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
706   for (k=0; k<coloring->ncolors; k++) {
707     /*
708        Loop over each column associated with color adding the
709        perturbation to the vector w3.
710     */
711     for (l=0; l<coloring->ncolumns[k]; l++) {
712       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
713       dx  = xx[col];
714       if (dx == 0.0) dx = 1.0;
715 #if !defined(PETSC_USE_COMPLEX)
716       if (dx < umin && dx >= 0.0)      dx = umin;
717       else if (dx < 0.0 && dx > -umin) dx = -umin;
718 #else
719       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
720       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
721 #endif
722       dx                *= epsilon;
723       vscale_array[col] = 1.0/dx;
724     }
725   }
726   vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
727   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
728   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
729 
730   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
731   else                        vscaleforrow = coloring->columnsforrow;
732 
733   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
734   /*
735       Loop over each color
736   */
737   for (k=0; k<coloring->ncolors; k++) {
738     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
739     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
740     /*
741        Loop over each column associated with color adding the
742        perturbation to the vector w3.
743     */
744     for (l=0; l<coloring->ncolumns[k]; l++) {
745       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
746       dx  = xx[col];
747       if (dx == 0.0) dx = 1.0;
748 #if !defined(PETSC_USE_COMPLEX)
749       if (dx < umin && dx >= 0.0)      dx = umin;
750       else if (dx < 0.0 && dx > -umin) dx = -umin;
751 #else
752       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
753       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
754 #endif
755       dx            *= epsilon;
756       w3_array[col] += dx;
757     }
758     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
759 
760     /*
761        Evaluate function at x1 + dx (here dx is a vector of perturbations)
762     */
763     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
764     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
765 
766     /*
767        Loop over rows of vector, putting results into Jacobian matrix
768     */
769     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
770     for (l=0; l<coloring->nrows[k]; l++) {
771       row    = coloring->rows[k][l];
772       col    = coloring->columnsforrow[k][l];
773       y[row] *= vscale_array[vscaleforrow[k][l]];
774       srow   = row + start;
775       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
776     }
777     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
778   }
779   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
780   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
781   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
782   PLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);
783   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
784   PetscFunctionReturn(0);
785 }
786 
787 
788 
789