xref: /petsc/src/mat/matfd/fdmatrix.c (revision ea709b57ddb8cc304f11df2e9a39d6a8fdb28b53)
1*ea709b57SSatish Balay /*$Id: fdmatrix.c,v 1.90 2001/08/06 21:16:12 bsmith Exp balay $*/
2bbf0e169SBarry Smith 
3bbf0e169SBarry Smith /*
4639f9d9dSBarry Smith    This is where the abstract matrix operations are defined that are
5639f9d9dSBarry Smith   used for finite difference computations of Jacobians using coloring.
6bbf0e169SBarry Smith */
7bbf0e169SBarry Smith 
8bbf0e169SBarry Smith #include "petsc.h"
9e090d566SSatish Balay #include "src/mat/matimpl.h"        /*I "petscmat.h" I*/
10bbf0e169SBarry Smith 
114a2ae208SSatish Balay #undef __FUNCT__
123a7fca6bSBarry Smith #define __FUNCT__ "MatFDColoringSetF"
133a7fca6bSBarry Smith int MatFDColoringSetF(MatFDColoring fd,Vec F)
143a7fca6bSBarry Smith {
153a7fca6bSBarry Smith   PetscFunctionBegin;
163a7fca6bSBarry Smith   fd->F = F;
173a7fca6bSBarry Smith   PetscFunctionReturn(0);
183a7fca6bSBarry Smith }
193a7fca6bSBarry Smith 
203a7fca6bSBarry Smith #undef __FUNCT__
214a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw_Zoom"
22b0a32e0cSBarry Smith static int MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
239194eea9SBarry Smith {
249194eea9SBarry Smith   MatFDColoring fd = (MatFDColoring)Aa;
259194eea9SBarry Smith   int           ierr,i,j;
269194eea9SBarry Smith   PetscReal     x,y;
279194eea9SBarry Smith 
289194eea9SBarry Smith   PetscFunctionBegin;
299194eea9SBarry Smith 
309194eea9SBarry Smith   /* loop over colors  */
319194eea9SBarry Smith   for (i=0; i<fd->ncolors; i++) {
329194eea9SBarry Smith     for (j=0; j<fd->nrows[i]; j++) {
339194eea9SBarry Smith       y = fd->M - fd->rows[i][j] - fd->rstart;
349194eea9SBarry Smith       x = fd->columnsforrow[i][j];
35b0a32e0cSBarry Smith       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
369194eea9SBarry Smith     }
379194eea9SBarry Smith   }
389194eea9SBarry Smith   PetscFunctionReturn(0);
399194eea9SBarry Smith }
409194eea9SBarry Smith 
414a2ae208SSatish Balay #undef __FUNCT__
424a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw"
43b0a32e0cSBarry Smith static int MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
44005c665bSBarry Smith {
459194eea9SBarry Smith   int         ierr;
46005c665bSBarry Smith   PetscTruth  isnull;
47b0a32e0cSBarry Smith   PetscDraw   draw;
4854d96fa3SBarry Smith   PetscReal   xr,yr,xl,yl,h,w;
49005c665bSBarry Smith 
503a40ed3dSBarry Smith   PetscFunctionBegin;
51b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
52b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
539194eea9SBarry Smith 
549194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
55005c665bSBarry Smith 
56005c665bSBarry Smith   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
57005c665bSBarry Smith   xr += w;     yr += h;    xl = -w;     yl = -h;
58b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
59b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
609194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
613a40ed3dSBarry Smith   PetscFunctionReturn(0);
62005c665bSBarry Smith }
63005c665bSBarry Smith 
644a2ae208SSatish Balay #undef __FUNCT__
654a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView"
66bbf0e169SBarry Smith /*@C
67639f9d9dSBarry Smith    MatFDColoringView - Views a finite difference coloring context.
68bbf0e169SBarry Smith 
694c49b128SBarry Smith    Collective on MatFDColoring
70fee21e36SBarry Smith 
71ef5ee4d1SLois Curfman McInnes    Input  Parameters:
72ef5ee4d1SLois Curfman McInnes +  c - the coloring context
73ef5ee4d1SLois Curfman McInnes -  viewer - visualization context
74ef5ee4d1SLois Curfman McInnes 
7515091d37SBarry Smith    Level: intermediate
7615091d37SBarry Smith 
77b4fc646aSLois Curfman McInnes    Notes:
78b4fc646aSLois Curfman McInnes    The available visualization contexts include
79b0a32e0cSBarry Smith +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
80b0a32e0cSBarry Smith .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
81ef5ee4d1SLois Curfman McInnes         output where only the first processor opens
82ef5ee4d1SLois Curfman McInnes         the file.  All other processors send their
83ef5ee4d1SLois Curfman McInnes         data to the first processor to print.
84b0a32e0cSBarry Smith -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
85bbf0e169SBarry Smith 
869194eea9SBarry Smith    Notes:
879194eea9SBarry Smith      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
88b0a32e0cSBarry Smith    involves more than 33 then some seemingly identical colors are displayed making it look
899194eea9SBarry Smith    like an illegal coloring. This is just a graphical artifact.
909194eea9SBarry Smith 
91639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
92005c665bSBarry Smith 
93b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, view
94bbf0e169SBarry Smith @*/
95b0a32e0cSBarry Smith int MatFDColoringView(MatFDColoring c,PetscViewer viewer)
96bbf0e169SBarry Smith {
97fb9695e5SSatish Balay   int               i,j,ierr;
986831982aSBarry Smith   PetscTruth        isdraw,isascii;
99f3ef73ceSBarry Smith   PetscViewerFormat format;
100bbf0e169SBarry Smith 
1013a40ed3dSBarry Smith   PetscFunctionBegin;
102b4fc646aSLois Curfman McInnes   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
103b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(c->comm);
104b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
1056831982aSBarry Smith   PetscCheckSameComm(c,viewer);
106bbf0e169SBarry Smith 
107fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
108b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
1090f5bd95cSBarry Smith   if (isdraw) {
110b4fc646aSLois Curfman McInnes     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
1110f5bd95cSBarry Smith   } else if (isascii) {
112b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"MatFDColoring Object:\n");CHKERRQ(ierr);
113b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",c->error_rel);CHKERRQ(ierr);
114b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%g\n",c->umin);CHKERRQ(ierr);
115b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%d\n",c->ncolors);CHKERRQ(ierr);
116ae09f205SBarry Smith 
117b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
118fb9695e5SSatish Balay     if (format != PETSC_VIEWER_ASCII_INFO) {
119b4fc646aSLois Curfman McInnes       for (i=0; i<c->ncolors; i++) {
120b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %d\n",i);CHKERRQ(ierr);
121b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %d\n",c->ncolumns[i]);CHKERRQ(ierr);
122b4fc646aSLois Curfman McInnes         for (j=0; j<c->ncolumns[i]; j++) {
123b0a32e0cSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %d\n",c->columns[i][j]);CHKERRQ(ierr);
124639f9d9dSBarry Smith         }
125b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %d\n",c->nrows[i]);CHKERRQ(ierr);
126b4fc646aSLois Curfman McInnes         for (j=0; j<c->nrows[i]; j++) {
127b0a32e0cSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %d %d \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
128b4fc646aSLois Curfman McInnes         }
129bbf0e169SBarry Smith       }
130bbf0e169SBarry Smith     }
131b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1325cd90555SBarry Smith   } else {
13329bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
134bbf0e169SBarry Smith   }
1353a40ed3dSBarry Smith   PetscFunctionReturn(0);
136639f9d9dSBarry Smith }
137639f9d9dSBarry Smith 
1384a2ae208SSatish Balay #undef __FUNCT__
1394a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetParameters"
140639f9d9dSBarry Smith /*@
141b4fc646aSLois Curfman McInnes    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
142b4fc646aSLois Curfman McInnes    a Jacobian matrix using finite differences.
143639f9d9dSBarry Smith 
144ef5ee4d1SLois Curfman McInnes    Collective on MatFDColoring
145ef5ee4d1SLois Curfman McInnes 
146ef5ee4d1SLois Curfman McInnes    The Jacobian is estimated with the differencing approximation
147ef5ee4d1SLois Curfman McInnes .vb
14865f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
149f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
150f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
151ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
152ef5ee4d1SLois Curfman McInnes .ve
153639f9d9dSBarry Smith 
154639f9d9dSBarry Smith    Input Parameters:
155ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
156639f9d9dSBarry Smith .  error_rel - relative error
157f23b5b22SLois Curfman McInnes -  umin - minimum allowable u-value magnitude
158fee21e36SBarry Smith 
15915091d37SBarry Smith    Level: advanced
16015091d37SBarry Smith 
161b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, parameters
162b4fc646aSLois Curfman McInnes 
163b4fc646aSLois Curfman McInnes .seealso: MatFDColoringCreate()
164639f9d9dSBarry Smith @*/
165329f5518SBarry Smith int MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
166639f9d9dSBarry Smith {
1673a40ed3dSBarry Smith   PetscFunctionBegin;
168639f9d9dSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
169639f9d9dSBarry Smith 
170639f9d9dSBarry Smith   if (error != PETSC_DEFAULT) matfd->error_rel = error;
171639f9d9dSBarry Smith   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
1723a40ed3dSBarry Smith   PetscFunctionReturn(0);
173639f9d9dSBarry Smith }
174639f9d9dSBarry Smith 
1754a2ae208SSatish Balay #undef __FUNCT__
1764a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFrequency"
177005c665bSBarry Smith /*@
178e0907662SLois Curfman McInnes    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
179e0907662SLois Curfman McInnes    matrices.
180005c665bSBarry Smith 
181fee21e36SBarry Smith    Collective on MatFDColoring
182fee21e36SBarry Smith 
183ef5ee4d1SLois Curfman McInnes    Input Parameters:
184ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
185ef5ee4d1SLois Curfman McInnes -  freq - frequency (default is 1)
186ef5ee4d1SLois Curfman McInnes 
18715091d37SBarry Smith    Options Database Keys:
18815091d37SBarry Smith .  -mat_fd_coloring_freq <freq>  - Sets coloring frequency
18915091d37SBarry Smith 
19015091d37SBarry Smith    Level: advanced
19115091d37SBarry Smith 
192e0907662SLois Curfman McInnes    Notes:
193e0907662SLois Curfman McInnes    Using a modified Newton strategy, where the Jacobian remains fixed for several
194e0907662SLois Curfman McInnes    iterations, can be cost effective in terms of overall nonlinear solution
195e0907662SLois Curfman McInnes    efficiency.  This parameter indicates that a new Jacobian will be computed every
196e0907662SLois Curfman McInnes    <freq> nonlinear iterations.
197e0907662SLois Curfman McInnes 
198b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, frequency
199ef5ee4d1SLois Curfman McInnes 
20040964ad5SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency(), MatFDColoringSetRecompute()
201005c665bSBarry Smith @*/
202005c665bSBarry Smith int MatFDColoringSetFrequency(MatFDColoring matfd,int freq)
203005c665bSBarry Smith {
2043a40ed3dSBarry Smith   PetscFunctionBegin;
205005c665bSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
206005c665bSBarry Smith 
207005c665bSBarry Smith   matfd->freq = freq;
2083a40ed3dSBarry Smith   PetscFunctionReturn(0);
209005c665bSBarry Smith }
210005c665bSBarry Smith 
2114a2ae208SSatish Balay #undef __FUNCT__
2124a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringGetFrequency"
213ff0cfa39SBarry Smith /*@
214ff0cfa39SBarry Smith    MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian
215ff0cfa39SBarry Smith    matrices.
216ff0cfa39SBarry Smith 
217ef5ee4d1SLois Curfman McInnes    Not Collective
218ef5ee4d1SLois Curfman McInnes 
219ff0cfa39SBarry Smith    Input Parameters:
220ff0cfa39SBarry Smith .  coloring - the coloring context
221ff0cfa39SBarry Smith 
222ff0cfa39SBarry Smith    Output Parameters:
223ff0cfa39SBarry Smith .  freq - frequency (default is 1)
224ff0cfa39SBarry Smith 
22515091d37SBarry Smith    Options Database Keys:
22615091d37SBarry Smith .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
22715091d37SBarry Smith 
22815091d37SBarry Smith    Level: advanced
22915091d37SBarry Smith 
230ff0cfa39SBarry Smith    Notes:
231ff0cfa39SBarry Smith    Using a modified Newton strategy, where the Jacobian remains fixed for several
232ff0cfa39SBarry Smith    iterations, can be cost effective in terms of overall nonlinear solution
233ff0cfa39SBarry Smith    efficiency.  This parameter indicates that a new Jacobian will be computed every
234ff0cfa39SBarry Smith    <freq> nonlinear iterations.
235ff0cfa39SBarry Smith 
236ff0cfa39SBarry Smith .keywords: Mat, finite differences, coloring, get, frequency
237ef5ee4d1SLois Curfman McInnes 
238ef5ee4d1SLois Curfman McInnes .seealso: MatFDColoringSetFrequency()
239ff0cfa39SBarry Smith @*/
240ff0cfa39SBarry Smith int MatFDColoringGetFrequency(MatFDColoring matfd,int *freq)
241ff0cfa39SBarry Smith {
2423a40ed3dSBarry Smith   PetscFunctionBegin;
243ff0cfa39SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
244ff0cfa39SBarry Smith 
245ff0cfa39SBarry Smith   *freq = matfd->freq;
2463a40ed3dSBarry Smith   PetscFunctionReturn(0);
247ff0cfa39SBarry Smith }
248ff0cfa39SBarry Smith 
2494a2ae208SSatish Balay #undef __FUNCT__
2504a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFunction"
251d64ed03dSBarry Smith /*@C
252005c665bSBarry Smith    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
253005c665bSBarry Smith 
254fee21e36SBarry Smith    Collective on MatFDColoring
255fee21e36SBarry Smith 
256ef5ee4d1SLois Curfman McInnes    Input Parameters:
257ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
258ef5ee4d1SLois Curfman McInnes .  f - the function
259ef5ee4d1SLois Curfman McInnes -  fctx - the optional user-defined function context
260ef5ee4d1SLois Curfman McInnes 
26115091d37SBarry Smith    Level: intermediate
26215091d37SBarry Smith 
263f881d145SBarry Smith    Notes:
264f881d145SBarry Smith     In Fortran you must call MatFDColoringSetFunctionSNES() for a coloring object to
265f881d145SBarry Smith   be used with the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used
266f881d145SBarry Smith   with the TS solvers.
267f881d145SBarry Smith 
268b4fc646aSLois Curfman McInnes .keywords: Mat, Jacobian, finite differences, set, function
269005c665bSBarry Smith @*/
270840b8ebdSBarry Smith int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void),void *fctx)
271005c665bSBarry Smith {
2723a40ed3dSBarry Smith   PetscFunctionBegin;
273005c665bSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
274005c665bSBarry Smith 
275005c665bSBarry Smith   matfd->f    = f;
276005c665bSBarry Smith   matfd->fctx = fctx;
277005c665bSBarry Smith 
2783a40ed3dSBarry Smith   PetscFunctionReturn(0);
279005c665bSBarry Smith }
280005c665bSBarry Smith 
2814a2ae208SSatish Balay #undef __FUNCT__
2824a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFromOptions"
283639f9d9dSBarry Smith /*@
284b4fc646aSLois Curfman McInnes    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
285639f9d9dSBarry Smith    the options database.
286639f9d9dSBarry Smith 
287fee21e36SBarry Smith    Collective on MatFDColoring
288fee21e36SBarry Smith 
28965f2ba5bSLois Curfman McInnes    The Jacobian, F'(u), is estimated with the differencing approximation
290ef5ee4d1SLois Curfman McInnes .vb
29165f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
292f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
293f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
294ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
295ef5ee4d1SLois Curfman McInnes .ve
296ef5ee4d1SLois Curfman McInnes 
297ef5ee4d1SLois Curfman McInnes    Input Parameter:
298ef5ee4d1SLois Curfman McInnes .  coloring - the coloring context
299ef5ee4d1SLois Curfman McInnes 
300b4fc646aSLois Curfman McInnes    Options Database Keys:
301d15ffeeaSSatish Balay +  -mat_fd_coloring_err <err> - Sets <err> (square root
302ef5ee4d1SLois Curfman McInnes            of relative error in the function)
303f23b5b22SLois Curfman McInnes .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
304ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian
305ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view - Activates basic viewing
306ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view_info - Activates viewing info
307ef5ee4d1SLois Curfman McInnes -  -mat_fd_coloring_view_draw - Activates drawing
308639f9d9dSBarry Smith 
30915091d37SBarry Smith     Level: intermediate
31015091d37SBarry Smith 
311b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, parameters
312d1c39f55SBarry Smith 
313d1c39f55SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
314d1c39f55SBarry Smith 
315639f9d9dSBarry Smith @*/
316639f9d9dSBarry Smith int MatFDColoringSetFromOptions(MatFDColoring matfd)
317639f9d9dSBarry Smith {
318186905e3SBarry Smith   int        ierr;
3193a40ed3dSBarry Smith 
3203a40ed3dSBarry Smith   PetscFunctionBegin;
321639f9d9dSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
322639f9d9dSBarry Smith 
323b0a32e0cSBarry Smith   ierr = PetscOptionsBegin(matfd->comm,matfd->prefix,"Jacobian computation via finite differences option","MatFD");CHKERRQ(ierr);
32487828ca2SBarry Smith     ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
32587828ca2SBarry Smith     ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
326b0a32e0cSBarry Smith     ierr = PetscOptionsInt("-mat_fd_coloring_freq","How often Jacobian is recomputed","MatFDColoringSetFrequency",matfd->freq,&matfd->freq,0);CHKERRQ(ierr);
327186905e3SBarry Smith     /* not used here; but so they are presented in the GUI */
328b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view","Print entire datastructure used for Jacobian","None",0);CHKERRQ(ierr);
329b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view_info","Print number of colors etc for Jacobian","None",0);CHKERRQ(ierr);
330b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view_draw","Plot nonzero structure ofJacobian","None",0);CHKERRQ(ierr);
331b0a32e0cSBarry Smith   PetscOptionsEnd();CHKERRQ(ierr);
3323a40ed3dSBarry Smith   PetscFunctionReturn(0);
333005c665bSBarry Smith }
334005c665bSBarry Smith 
3354a2ae208SSatish Balay #undef __FUNCT__
3364a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Private"
337005c665bSBarry Smith int MatFDColoringView_Private(MatFDColoring fd)
338005c665bSBarry Smith {
339f1af5d2fSBarry Smith   int        ierr;
340f1af5d2fSBarry Smith   PetscTruth flg;
341005c665bSBarry Smith 
3423a40ed3dSBarry Smith   PetscFunctionBegin;
343b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr);
344005c665bSBarry Smith   if (flg) {
345b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
346005c665bSBarry Smith   }
347b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr);
348ae09f205SBarry Smith   if (flg) {
349fb9695e5SSatish Balay     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(fd->comm),PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
350b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
351b0a32e0cSBarry Smith     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
352ae09f205SBarry Smith   }
353b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr);
354005c665bSBarry Smith   if (flg) {
355b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
356b0a32e0cSBarry Smith     ierr = PetscViewerFlush(PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
357005c665bSBarry Smith   }
3583a40ed3dSBarry Smith   PetscFunctionReturn(0);
359bbf0e169SBarry Smith }
360bbf0e169SBarry Smith 
3614a2ae208SSatish Balay #undef __FUNCT__
3624a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringCreate"
363bbf0e169SBarry Smith /*@C
364639f9d9dSBarry Smith    MatFDColoringCreate - Creates a matrix coloring context for finite difference
365639f9d9dSBarry Smith    computation of Jacobians.
366bbf0e169SBarry Smith 
367ef5ee4d1SLois Curfman McInnes    Collective on Mat
368ef5ee4d1SLois Curfman McInnes 
369639f9d9dSBarry Smith    Input Parameters:
370ef5ee4d1SLois Curfman McInnes +  mat - the matrix containing the nonzero structure of the Jacobian
371ef5ee4d1SLois Curfman McInnes -  iscoloring - the coloring of the matrix
372bbf0e169SBarry Smith 
373bbf0e169SBarry Smith     Output Parameter:
374639f9d9dSBarry Smith .   color - the new coloring context
375bbf0e169SBarry Smith 
376b4fc646aSLois Curfman McInnes     Options Database Keys:
377ef5ee4d1SLois Curfman McInnes +    -mat_fd_coloring_view - Activates basic viewing or coloring
378ef5ee4d1SLois Curfman McInnes .    -mat_fd_coloring_view_draw - Activates drawing of coloring
379ef5ee4d1SLois Curfman McInnes -    -mat_fd_coloring_view_info - Activates viewing of coloring info
380639f9d9dSBarry Smith 
38115091d37SBarry Smith     Level: intermediate
38215091d37SBarry Smith 
3836831982aSBarry Smith .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
384d1c39f55SBarry Smith           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
385d1c39f55SBarry Smith           MatFDColoringSetFrequency(), MatFDColoringSetRecompute(), MatFDColoringView(),
386d1c39f55SBarry Smith           MatFDColoringSetParameters()
387bbf0e169SBarry Smith @*/
388639f9d9dSBarry Smith int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
389bbf0e169SBarry Smith {
390639f9d9dSBarry Smith   MatFDColoring c;
391639f9d9dSBarry Smith   MPI_Comm      comm;
392639f9d9dSBarry Smith   int           ierr,M,N;
393639f9d9dSBarry Smith 
3943a40ed3dSBarry Smith   PetscFunctionBegin;
395b0a32e0cSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
396639f9d9dSBarry Smith   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
39729bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Only for square matrices");
398639f9d9dSBarry Smith 
399f881d145SBarry Smith   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4009194eea9SBarry Smith   PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView);
401b0a32e0cSBarry Smith   PetscLogObjectCreate(c);
402639f9d9dSBarry Smith 
403f830108cSBarry Smith   if (mat->ops->fdcoloringcreate) {
404f830108cSBarry Smith     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
405639f9d9dSBarry Smith   } else {
40629bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Code not yet written for this matrix type");
407639f9d9dSBarry Smith   }
408639f9d9dSBarry Smith 
409639f9d9dSBarry Smith   c->error_rel         = 1.e-8;
410ae09f205SBarry Smith   c->umin              = 1.e-6;
411005c665bSBarry Smith   c->freq              = 1;
41240964ad5SBarry Smith   c->usersetsrecompute = PETSC_FALSE;
41340964ad5SBarry Smith   c->recompute         = PETSC_FALSE;
414005c665bSBarry Smith 
415005c665bSBarry Smith   ierr = MatFDColoringView_Private(c);CHKERRQ(ierr);
416639f9d9dSBarry Smith 
417639f9d9dSBarry Smith   *color = c;
418b0a32e0cSBarry Smith   ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
4193a40ed3dSBarry Smith   PetscFunctionReturn(0);
420bbf0e169SBarry Smith }
421bbf0e169SBarry Smith 
4224a2ae208SSatish Balay #undef __FUNCT__
4234a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringDestroy"
424bbf0e169SBarry Smith /*@C
425639f9d9dSBarry Smith     MatFDColoringDestroy - Destroys a matrix coloring context that was created
426639f9d9dSBarry Smith     via MatFDColoringCreate().
427bbf0e169SBarry Smith 
428ef5ee4d1SLois Curfman McInnes     Collective on MatFDColoring
429ef5ee4d1SLois Curfman McInnes 
430b4fc646aSLois Curfman McInnes     Input Parameter:
431639f9d9dSBarry Smith .   c - coloring context
432bbf0e169SBarry Smith 
43315091d37SBarry Smith     Level: intermediate
43415091d37SBarry Smith 
435639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
436bbf0e169SBarry Smith @*/
437639f9d9dSBarry Smith int MatFDColoringDestroy(MatFDColoring c)
438bbf0e169SBarry Smith {
439263760aaSBarry Smith   int i,ierr;
440bbf0e169SBarry Smith 
4413a40ed3dSBarry Smith   PetscFunctionBegin;
4423a40ed3dSBarry Smith   if (--c->refct > 0) PetscFunctionReturn(0);
443d4bb536fSBarry Smith 
444639f9d9dSBarry Smith   for (i=0; i<c->ncolors; i++) {
445606d414cSSatish Balay     if (c->columns[i])         {ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);}
446606d414cSSatish Balay     if (c->rows[i])            {ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);}
447606d414cSSatish Balay     if (c->columnsforrow[i])   {ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);}
44830b34957SBarry Smith     if (c->vscaleforrow && c->vscaleforrow[i]) {ierr = PetscFree(c->vscaleforrow[i]);CHKERRQ(ierr);}
449bbf0e169SBarry Smith   }
450606d414cSSatish Balay   ierr = PetscFree(c->ncolumns);CHKERRQ(ierr);
451606d414cSSatish Balay   ierr = PetscFree(c->columns);CHKERRQ(ierr);
452606d414cSSatish Balay   ierr = PetscFree(c->nrows);CHKERRQ(ierr);
453606d414cSSatish Balay   ierr = PetscFree(c->rows);CHKERRQ(ierr);
454606d414cSSatish Balay   ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr);
45530b34957SBarry Smith   if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);}
4564f113abfSBarry Smith   if (c->vscale)       {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);}
457005c665bSBarry Smith   if (c->w1) {
458005c665bSBarry Smith     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
459005c665bSBarry Smith     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
460005c665bSBarry Smith     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
461005c665bSBarry Smith   }
462b0a32e0cSBarry Smith   PetscLogObjectDestroy(c);
463639f9d9dSBarry Smith   PetscHeaderDestroy(c);
4643a40ed3dSBarry Smith   PetscFunctionReturn(0);
465bbf0e169SBarry Smith }
46643a90d84SBarry Smith 
4674a2ae208SSatish Balay #undef __FUNCT__
4684a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApply"
46943a90d84SBarry Smith /*@
470e0907662SLois Curfman McInnes     MatFDColoringApply - Given a matrix for which a MatFDColoring context
471e0907662SLois Curfman McInnes     has been created, computes the Jacobian for a function via finite differences.
47243a90d84SBarry Smith 
473fee21e36SBarry Smith     Collective on MatFDColoring
474fee21e36SBarry Smith 
475ef5ee4d1SLois Curfman McInnes     Input Parameters:
476ef5ee4d1SLois Curfman McInnes +   mat - location to store Jacobian
477ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
478ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
479ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
480ef5ee4d1SLois Curfman McInnes 
4818bba8e72SBarry Smith    Options Database Keys:
482ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
4838bba8e72SBarry Smith 
48415091d37SBarry Smith    Level: intermediate
48515091d37SBarry Smith 
48643a90d84SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
48743a90d84SBarry Smith 
48843a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences
48943a90d84SBarry Smith @*/
490005c665bSBarry Smith int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
49143a90d84SBarry Smith {
4925904e1b1SBarry Smith   int           (*f)(void *,Vec,Vec,void*) = (int (*)(void *,Vec,Vec,void *))coloring->f;
4933a7fca6bSBarry Smith   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
494*ea709b57SSatish Balay   PetscScalar   dx,mone = -1.0,*y,*xx,*w3_array;
495*ea709b57SSatish Balay   PetscScalar   *vscale_array;
496329f5518SBarry Smith   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
497005c665bSBarry Smith   Vec           w1,w2,w3;
498005c665bSBarry Smith   void          *fctx = coloring->fctx;
499f1af5d2fSBarry Smith   PetscTruth    flg;
500005c665bSBarry Smith 
501a2e34c3dSBarry Smith 
5023a40ed3dSBarry Smith   PetscFunctionBegin;
503e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(J,MAT_COOKIE);
504e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
505e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(x1,VEC_COOKIE);
506e0907662SLois Curfman McInnes 
50740964ad5SBarry Smith   if (coloring->usersetsrecompute) {
50840964ad5SBarry Smith     if (!coloring->recompute) {
50940964ad5SBarry Smith       *flag = SAME_PRECONDITIONER;
51076d8deaeSBarry Smith       PetscLogInfo(J,"MatFDColoringApply:Skipping Jacobian, since user called MatFDColorSetRecompute()\n");
51140964ad5SBarry Smith       PetscFunctionReturn(0);
51240964ad5SBarry Smith     } else {
51340964ad5SBarry Smith       coloring->recompute = PETSC_FALSE;
51440964ad5SBarry Smith     }
51540964ad5SBarry Smith   }
51640964ad5SBarry Smith 
517b0a32e0cSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
51876d8deaeSBarry Smith   if (J->ops->fdcoloringapply) {
51976d8deaeSBarry Smith     ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr);
52076d8deaeSBarry Smith   } else {
52176d8deaeSBarry Smith 
522005c665bSBarry Smith     if (!coloring->w1) {
523005c665bSBarry Smith       ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
524b0a32e0cSBarry Smith       PetscLogObjectParent(coloring,coloring->w1);
525005c665bSBarry Smith       ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
526b0a32e0cSBarry Smith       PetscLogObjectParent(coloring,coloring->w2);
527005c665bSBarry Smith       ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
528b0a32e0cSBarry Smith       PetscLogObjectParent(coloring,coloring->w3);
529005c665bSBarry Smith     }
530005c665bSBarry Smith     w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
53143a90d84SBarry Smith 
5324c49b128SBarry Smith     ierr = MatSetUnfactored(J);CHKERRQ(ierr);
533b0a32e0cSBarry Smith     ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
534f1af5d2fSBarry Smith     if (flg) {
535b0a32e0cSBarry Smith       PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
536e0907662SLois Curfman McInnes     } else {
53743a90d84SBarry Smith       ierr = MatZeroEntries(J);CHKERRQ(ierr);
538e0907662SLois Curfman McInnes     }
53943a90d84SBarry Smith 
54043a90d84SBarry Smith     ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
54143a90d84SBarry Smith     ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
542be2fbe1fSBarry Smith 
5433a7fca6bSBarry Smith     /*
5443a7fca6bSBarry Smith       This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
5453a7fca6bSBarry Smith       coloring->F for the coarser grids from the finest
5463a7fca6bSBarry Smith     */
5473a7fca6bSBarry Smith     if (coloring->F) {
5483a7fca6bSBarry Smith       ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
5493a7fca6bSBarry Smith       ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
5503a7fca6bSBarry Smith       if (m1 != m2) {
5513a7fca6bSBarry Smith 	coloring->F = 0;
5523a7fca6bSBarry Smith       }
5533a7fca6bSBarry Smith     }
5543a7fca6bSBarry Smith 
555be2fbe1fSBarry Smith     if (coloring->F) {
556be2fbe1fSBarry Smith       w1          = coloring->F; /* use already computed value of function */
557be2fbe1fSBarry Smith       coloring->F = 0;
558be2fbe1fSBarry Smith     } else {
55943a90d84SBarry Smith       ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
560be2fbe1fSBarry Smith     }
56143a90d84SBarry Smith 
56243a90d84SBarry Smith     /*
5639782cf98SBarry Smith        Compute all the scale factors and share with other processors
5649782cf98SBarry Smith     */
5659782cf98SBarry Smith     ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
5664f113abfSBarry Smith     ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
5679782cf98SBarry Smith     for (k=0; k<coloring->ncolors; k++) {
5689782cf98SBarry Smith       /*
5699782cf98SBarry Smith 	Loop over each column associated with color adding the
5709782cf98SBarry Smith 	perturbation to the vector w3.
5719782cf98SBarry Smith       */
5729782cf98SBarry Smith       for (l=0; l<coloring->ncolumns[k]; l++) {
5739782cf98SBarry Smith 	col = coloring->columns[k][l];    /* column of the matrix we are probing for */
5749782cf98SBarry Smith 	dx  = xx[col];
5759782cf98SBarry Smith 	if (dx == 0.0) dx = 1.0;
5769782cf98SBarry Smith #if !defined(PETSC_USE_COMPLEX)
5779782cf98SBarry Smith 	if (dx < umin && dx >= 0.0)      dx = umin;
5789782cf98SBarry Smith 	else if (dx < 0.0 && dx > -umin) dx = -umin;
5799782cf98SBarry Smith #else
5809782cf98SBarry Smith 	if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
5819782cf98SBarry Smith 	else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
5829782cf98SBarry Smith #endif
5839782cf98SBarry Smith 	dx                *= epsilon;
58430b34957SBarry Smith 	vscale_array[col] = 1.0/dx;
5859782cf98SBarry Smith       }
5869782cf98SBarry Smith     }
587a2e34c3dSBarry Smith     vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
58830b34957SBarry Smith     ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
58930b34957SBarry Smith     ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5909782cf98SBarry Smith 
591ce1411ecSBarry Smith     /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
592ce1411ecSBarry Smith 	ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
593b0a32e0cSBarry Smith 
59430b34957SBarry Smith     if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
59530b34957SBarry Smith     else                        vscaleforrow = coloring->columnsforrow;
59630b34957SBarry Smith 
59730b34957SBarry Smith     ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
5989782cf98SBarry Smith     /*
59943a90d84SBarry Smith       Loop over each color
60043a90d84SBarry Smith     */
60143a90d84SBarry Smith     for (k=0; k<coloring->ncolors; k++) {
60243a90d84SBarry Smith       ierr = VecCopy(x1,w3);CHKERRQ(ierr);
60342460c72SBarry Smith       ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
60443a90d84SBarry Smith       /*
60543a90d84SBarry Smith 	Loop over each column associated with color adding the
60643a90d84SBarry Smith 	perturbation to the vector w3.
60743a90d84SBarry Smith       */
60843a90d84SBarry Smith       for (l=0; l<coloring->ncolumns[k]; l++) {
60943a90d84SBarry Smith 	col = coloring->columns[k][l];    /* column of the matrix we are probing for */
61042460c72SBarry Smith 	dx  = xx[col];
611ae09f205SBarry Smith 	if (dx == 0.0) dx = 1.0;
612aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
613ae09f205SBarry Smith 	if (dx < umin && dx >= 0.0)      dx = umin;
614ae09f205SBarry Smith 	else if (dx < 0.0 && dx > -umin) dx = -umin;
61543a90d84SBarry Smith #else
616329f5518SBarry Smith 	if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
617329f5518SBarry Smith 	else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
61843a90d84SBarry Smith #endif
61943a90d84SBarry Smith 	dx            *= epsilon;
62029bbc08cSBarry Smith 	if (!PetscAbsScalar(dx)) SETERRQ(1,"Computed 0 differencing parameter");
62142460c72SBarry Smith 	w3_array[col] += dx;
62243a90d84SBarry Smith       }
62342460c72SBarry Smith       w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
6243b28642cSBarry Smith 
62543a90d84SBarry Smith       /*
626e0907662SLois Curfman McInnes 	Evaluate function at x1 + dx (here dx is a vector of perturbations)
62743a90d84SBarry Smith       */
628a2e34c3dSBarry Smith 
62943a90d84SBarry Smith       ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
63043a90d84SBarry Smith       ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
6319782cf98SBarry Smith 
63243a90d84SBarry Smith       /*
633e0907662SLois Curfman McInnes 	Loop over rows of vector, putting results into Jacobian matrix
63443a90d84SBarry Smith       */
6353b28642cSBarry Smith       ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
63643a90d84SBarry Smith       for (l=0; l<coloring->nrows[k]; l++) {
63743a90d84SBarry Smith 	row    = coloring->rows[k][l];
63843a90d84SBarry Smith 	col    = coloring->columnsforrow[k][l];
6395904e1b1SBarry Smith 	y[row] *= vscale_array[vscaleforrow[k][l]];
64043a90d84SBarry Smith 	srow   = row + start;
64143a90d84SBarry Smith 	ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
64243a90d84SBarry Smith       }
6433b28642cSBarry Smith       ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
64443a90d84SBarry Smith     }
64530b34957SBarry Smith     ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
64642460c72SBarry Smith     xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
64743a90d84SBarry Smith     ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64843a90d84SBarry Smith     ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64976d8deaeSBarry Smith   }
650b0a32e0cSBarry Smith   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
651a2e34c3dSBarry Smith 
652b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test",&flg);CHKERRQ(ierr);
653a2e34c3dSBarry Smith   if (flg) {
654a2e34c3dSBarry Smith     ierr = MatNullSpaceTest(J->nullsp,J);CHKERRQ(ierr);
655a2e34c3dSBarry Smith   }
6563a40ed3dSBarry Smith   PetscFunctionReturn(0);
65743a90d84SBarry Smith }
658840b8ebdSBarry Smith 
6594a2ae208SSatish Balay #undef __FUNCT__
6604a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApplyTS"
661840b8ebdSBarry Smith /*@
662840b8ebdSBarry Smith     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
663840b8ebdSBarry Smith     has been created, computes the Jacobian for a function via finite differences.
664840b8ebdSBarry Smith 
665fee21e36SBarry Smith    Collective on Mat, MatFDColoring, and Vec
666fee21e36SBarry Smith 
667ef5ee4d1SLois Curfman McInnes     Input Parameters:
6683b28642cSBarry Smith +   mat - location to store Jacobian
669ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
670ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
671ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
672ef5ee4d1SLois Curfman McInnes 
673840b8ebdSBarry Smith    Options Database Keys:
674ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
675840b8ebdSBarry Smith 
67615091d37SBarry Smith    Level: intermediate
67715091d37SBarry Smith 
678840b8ebdSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
679840b8ebdSBarry Smith 
680840b8ebdSBarry Smith .keywords: coloring, Jacobian, finite differences
681840b8ebdSBarry Smith @*/
682329f5518SBarry Smith int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
683840b8ebdSBarry Smith {
684329f5518SBarry Smith   int           (*f)(void *,PetscReal,Vec,Vec,void*)=(int (*)(void *,PetscReal,Vec,Vec,void *))coloring->f;
6855904e1b1SBarry Smith   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow;
686*ea709b57SSatish Balay   PetscScalar   dx,mone = -1.0,*y,*xx,*w3_array;
687*ea709b57SSatish Balay   PetscScalar   *vscale_array;
688329f5518SBarry Smith   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
689840b8ebdSBarry Smith   Vec           w1,w2,w3;
690840b8ebdSBarry Smith   void          *fctx = coloring->fctx;
691f1af5d2fSBarry Smith   PetscTruth    flg;
692840b8ebdSBarry Smith 
6933a40ed3dSBarry Smith   PetscFunctionBegin;
694840b8ebdSBarry Smith   PetscValidHeaderSpecific(J,MAT_COOKIE);
695840b8ebdSBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
696840b8ebdSBarry Smith   PetscValidHeaderSpecific(x1,VEC_COOKIE);
697840b8ebdSBarry Smith 
698b0a32e0cSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
699840b8ebdSBarry Smith   if (!coloring->w1) {
700840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
701b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w1);
702840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
703b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w2);
704840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
705b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w3);
706840b8ebdSBarry Smith   }
707840b8ebdSBarry Smith   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
708840b8ebdSBarry Smith 
7095904e1b1SBarry Smith   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
710b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
711f1af5d2fSBarry Smith   if (flg) {
712b0a32e0cSBarry Smith     PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
713840b8ebdSBarry Smith   } else {
714840b8ebdSBarry Smith     ierr = MatZeroEntries(J);CHKERRQ(ierr);
715840b8ebdSBarry Smith   }
716840b8ebdSBarry Smith 
717840b8ebdSBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
718840b8ebdSBarry Smith   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
719840b8ebdSBarry Smith   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
720840b8ebdSBarry Smith 
721840b8ebdSBarry Smith   /*
7225904e1b1SBarry Smith       Compute all the scale factors and share with other processors
723840b8ebdSBarry Smith   */
7245904e1b1SBarry Smith   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
7255904e1b1SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
726840b8ebdSBarry Smith   for (k=0; k<coloring->ncolors; k++) {
727840b8ebdSBarry Smith     /*
728840b8ebdSBarry Smith        Loop over each column associated with color adding the
729840b8ebdSBarry Smith        perturbation to the vector w3.
730840b8ebdSBarry Smith     */
731840b8ebdSBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
732840b8ebdSBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
7335904e1b1SBarry Smith       dx  = xx[col];
734840b8ebdSBarry Smith       if (dx == 0.0) dx = 1.0;
735aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
736840b8ebdSBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
737840b8ebdSBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
738840b8ebdSBarry Smith #else
739329f5518SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
740329f5518SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
741840b8ebdSBarry Smith #endif
742840b8ebdSBarry Smith       dx                *= epsilon;
7435904e1b1SBarry Smith       vscale_array[col] = 1.0/dx;
744840b8ebdSBarry Smith     }
7455904e1b1SBarry Smith   }
7465904e1b1SBarry Smith   vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
7475904e1b1SBarry Smith   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7485904e1b1SBarry Smith   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7495904e1b1SBarry Smith 
7505904e1b1SBarry Smith   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
7515904e1b1SBarry Smith   else                        vscaleforrow = coloring->columnsforrow;
7525904e1b1SBarry Smith 
7535904e1b1SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
7545904e1b1SBarry Smith   /*
7555904e1b1SBarry Smith       Loop over each color
7565904e1b1SBarry Smith   */
7575904e1b1SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
7585904e1b1SBarry Smith     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
7595904e1b1SBarry Smith     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
7605904e1b1SBarry Smith     /*
7615904e1b1SBarry Smith        Loop over each column associated with color adding the
7625904e1b1SBarry Smith        perturbation to the vector w3.
7635904e1b1SBarry Smith     */
7645904e1b1SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
7655904e1b1SBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
7665904e1b1SBarry Smith       dx  = xx[col];
7675904e1b1SBarry Smith       if (dx == 0.0) dx = 1.0;
7685904e1b1SBarry Smith #if !defined(PETSC_USE_COMPLEX)
7695904e1b1SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
7705904e1b1SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
7715904e1b1SBarry Smith #else
7725904e1b1SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
7735904e1b1SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
7745904e1b1SBarry Smith #endif
7755904e1b1SBarry Smith       dx            *= epsilon;
7765904e1b1SBarry Smith       w3_array[col] += dx;
7775904e1b1SBarry Smith     }
7785904e1b1SBarry Smith     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
7795904e1b1SBarry Smith 
780840b8ebdSBarry Smith     /*
781840b8ebdSBarry Smith        Evaluate function at x1 + dx (here dx is a vector of perturbations)
782840b8ebdSBarry Smith     */
783840b8ebdSBarry Smith     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
784840b8ebdSBarry Smith     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
7855904e1b1SBarry Smith 
786840b8ebdSBarry Smith     /*
787840b8ebdSBarry Smith        Loop over rows of vector, putting results into Jacobian matrix
788840b8ebdSBarry Smith     */
7893b28642cSBarry Smith     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
790840b8ebdSBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
791840b8ebdSBarry Smith       row    = coloring->rows[k][l];
792840b8ebdSBarry Smith       col    = coloring->columnsforrow[k][l];
7935904e1b1SBarry Smith       y[row] *= vscale_array[vscaleforrow[k][l]];
794840b8ebdSBarry Smith       srow   = row + start;
795840b8ebdSBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
796840b8ebdSBarry Smith     }
7973b28642cSBarry Smith     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
798840b8ebdSBarry Smith   }
7995904e1b1SBarry Smith   ierr  = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
8005904e1b1SBarry Smith   xx    = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
801840b8ebdSBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
802840b8ebdSBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
803b0a32e0cSBarry Smith   ierr  = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
8043a40ed3dSBarry Smith   PetscFunctionReturn(0);
805840b8ebdSBarry Smith }
8063b28642cSBarry Smith 
8073b28642cSBarry Smith 
8084a2ae208SSatish Balay #undef __FUNCT__
8094a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetRecompute()"
81040964ad5SBarry Smith /*@C
81140964ad5SBarry Smith    MatFDColoringSetRecompute - Indicates that the next time a Jacobian preconditioner
81240964ad5SBarry Smith      is needed it sholuld be recomputed. Once this is called and the new Jacobian is computed
81340964ad5SBarry Smith      no additional Jacobian's will be computed (the same one will be used) until this is
81440964ad5SBarry Smith      called again.
81540964ad5SBarry Smith 
81640964ad5SBarry Smith    Collective on MatFDColoring
81740964ad5SBarry Smith 
81840964ad5SBarry Smith    Input  Parameters:
81940964ad5SBarry Smith .  c - the coloring context
82040964ad5SBarry Smith 
82140964ad5SBarry Smith    Level: intermediate
82240964ad5SBarry Smith 
82340964ad5SBarry Smith    Notes: The MatFDColoringSetFrequency() is ignored once this is called
82440964ad5SBarry Smith 
82540964ad5SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringSetFrequency()
82640964ad5SBarry Smith 
82740964ad5SBarry Smith .keywords: Mat, finite differences, coloring
82840964ad5SBarry Smith @*/
82940964ad5SBarry Smith int MatFDColoringSetRecompute(MatFDColoring c)
83040964ad5SBarry Smith {
83140964ad5SBarry Smith   PetscFunctionBegin;
83240964ad5SBarry Smith   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
83340964ad5SBarry Smith   c->usersetsrecompute = PETSC_TRUE;
83440964ad5SBarry Smith   c->recompute         = PETSC_TRUE;
83540964ad5SBarry Smith   PetscFunctionReturn(0);
83640964ad5SBarry Smith }
83740964ad5SBarry Smith 
8383b28642cSBarry Smith 
839