xref: /petsc/src/mat/matfd/fdmatrix.c (revision 4a2ae208534dc2960f861bf8a1e27d424854347f)
1*4a2ae208SSatish Balay /*$Id: fdmatrix.c,v 1.83 2001/01/22 23:05:09 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 
11*4a2ae208SSatish Balay #undef __FUNCT__
12*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw_Zoom"
13b0a32e0cSBarry Smith static int MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
149194eea9SBarry Smith {
159194eea9SBarry Smith   MatFDColoring fd = (MatFDColoring)Aa;
169194eea9SBarry Smith   int           ierr,i,j;
179194eea9SBarry Smith   PetscReal     x,y;
189194eea9SBarry Smith 
199194eea9SBarry Smith   PetscFunctionBegin;
209194eea9SBarry Smith 
219194eea9SBarry Smith   /* loop over colors  */
229194eea9SBarry Smith   for (i=0; i<fd->ncolors; i++) {
239194eea9SBarry Smith     for (j=0; j<fd->nrows[i]; j++) {
249194eea9SBarry Smith       y = fd->M - fd->rows[i][j] - fd->rstart;
259194eea9SBarry Smith       x = fd->columnsforrow[i][j];
26b0a32e0cSBarry Smith       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
279194eea9SBarry Smith     }
289194eea9SBarry Smith   }
299194eea9SBarry Smith   PetscFunctionReturn(0);
309194eea9SBarry Smith }
319194eea9SBarry Smith 
32*4a2ae208SSatish Balay #undef __FUNCT__
33*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw"
34b0a32e0cSBarry Smith static int MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
35005c665bSBarry Smith {
369194eea9SBarry Smith   int         ierr;
37005c665bSBarry Smith   PetscTruth  isnull;
38b0a32e0cSBarry Smith   PetscDraw        draw;
3954d96fa3SBarry Smith   PetscReal   xr,yr,xl,yl,h,w;
40005c665bSBarry Smith 
413a40ed3dSBarry Smith   PetscFunctionBegin;
42b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
43b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
449194eea9SBarry Smith 
459194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
46005c665bSBarry Smith 
47005c665bSBarry Smith   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
48005c665bSBarry Smith   xr += w;     yr += h;    xl = -w;     yl = -h;
49b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
50b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
519194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
523a40ed3dSBarry Smith   PetscFunctionReturn(0);
53005c665bSBarry Smith }
54005c665bSBarry Smith 
55*4a2ae208SSatish Balay #undef __FUNCT__
56*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView"
57bbf0e169SBarry Smith /*@C
58639f9d9dSBarry Smith    MatFDColoringView - Views a finite difference coloring context.
59bbf0e169SBarry Smith 
604c49b128SBarry Smith    Collective on MatFDColoring
61fee21e36SBarry Smith 
62ef5ee4d1SLois Curfman McInnes    Input  Parameters:
63ef5ee4d1SLois Curfman McInnes +  c - the coloring context
64ef5ee4d1SLois Curfman McInnes -  viewer - visualization context
65ef5ee4d1SLois Curfman McInnes 
6615091d37SBarry Smith    Level: intermediate
6715091d37SBarry Smith 
68b4fc646aSLois Curfman McInnes    Notes:
69b4fc646aSLois Curfman McInnes    The available visualization contexts include
70b0a32e0cSBarry Smith +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
71b0a32e0cSBarry Smith .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
72ef5ee4d1SLois Curfman McInnes         output where only the first processor opens
73ef5ee4d1SLois Curfman McInnes         the file.  All other processors send their
74ef5ee4d1SLois Curfman McInnes         data to the first processor to print.
75b0a32e0cSBarry Smith -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
76bbf0e169SBarry Smith 
779194eea9SBarry Smith    Notes:
789194eea9SBarry Smith      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
79b0a32e0cSBarry Smith    involves more than 33 then some seemingly identical colors are displayed making it look
809194eea9SBarry Smith    like an illegal coloring. This is just a graphical artifact.
819194eea9SBarry Smith 
82639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
83005c665bSBarry Smith 
84b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, view
85bbf0e169SBarry Smith @*/
86b0a32e0cSBarry Smith int MatFDColoringView(MatFDColoring c,PetscViewer viewer)
87bbf0e169SBarry Smith {
88fb9695e5SSatish Balay   int               i,j,ierr;
896831982aSBarry Smith   PetscTruth        isdraw,isascii;
90f3ef73ceSBarry Smith   PetscViewerFormat format;
91bbf0e169SBarry Smith 
923a40ed3dSBarry Smith   PetscFunctionBegin;
93b4fc646aSLois Curfman McInnes   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
94b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(c->comm);
95b0a32e0cSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE);
966831982aSBarry Smith   PetscCheckSameComm(c,viewer);
97bbf0e169SBarry Smith 
98fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
99b0a32e0cSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
1000f5bd95cSBarry Smith   if (isdraw) {
101b4fc646aSLois Curfman McInnes     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
1020f5bd95cSBarry Smith   } else if (isascii) {
103b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"MatFDColoring Object:\n");CHKERRQ(ierr);
104b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",c->error_rel);CHKERRQ(ierr);
105b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%g\n",c->umin);CHKERRQ(ierr);
106b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%d\n",c->ncolors);CHKERRQ(ierr);
107ae09f205SBarry Smith 
108b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
109fb9695e5SSatish Balay     if (format != PETSC_VIEWER_ASCII_INFO) {
110b4fc646aSLois Curfman McInnes       for (i=0; i<c->ncolors; i++) {
111b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %d\n",i);CHKERRQ(ierr);
112b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %d\n",c->ncolumns[i]);CHKERRQ(ierr);
113b4fc646aSLois Curfman McInnes         for (j=0; j<c->ncolumns[i]; j++) {
114b0a32e0cSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %d\n",c->columns[i][j]);CHKERRQ(ierr);
115639f9d9dSBarry Smith         }
116b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %d\n",c->nrows[i]);CHKERRQ(ierr);
117b4fc646aSLois Curfman McInnes         for (j=0; j<c->nrows[i]; j++) {
118b0a32e0cSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %d %d \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
119b4fc646aSLois Curfman McInnes         }
120bbf0e169SBarry Smith       }
121bbf0e169SBarry Smith     }
122b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1235cd90555SBarry Smith   } else {
12429bbc08cSBarry Smith     SETERRQ1(1,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
125bbf0e169SBarry Smith   }
1263a40ed3dSBarry Smith   PetscFunctionReturn(0);
127639f9d9dSBarry Smith }
128639f9d9dSBarry Smith 
129*4a2ae208SSatish Balay #undef __FUNCT__
130*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetParameters"
131639f9d9dSBarry Smith /*@
132b4fc646aSLois Curfman McInnes    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
133b4fc646aSLois Curfman McInnes    a Jacobian matrix using finite differences.
134639f9d9dSBarry Smith 
135ef5ee4d1SLois Curfman McInnes    Collective on MatFDColoring
136ef5ee4d1SLois Curfman McInnes 
137ef5ee4d1SLois Curfman McInnes    The Jacobian is estimated with the differencing approximation
138ef5ee4d1SLois Curfman McInnes .vb
13965f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
140f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
141f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
142ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
143ef5ee4d1SLois Curfman McInnes .ve
144639f9d9dSBarry Smith 
145639f9d9dSBarry Smith    Input Parameters:
146ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
147639f9d9dSBarry Smith .  error_rel - relative error
148f23b5b22SLois Curfman McInnes -  umin - minimum allowable u-value magnitude
149fee21e36SBarry Smith 
15015091d37SBarry Smith    Level: advanced
15115091d37SBarry Smith 
152b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, parameters
153b4fc646aSLois Curfman McInnes 
154b4fc646aSLois Curfman McInnes .seealso: MatFDColoringCreate()
155639f9d9dSBarry Smith @*/
156329f5518SBarry Smith int MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
157639f9d9dSBarry Smith {
1583a40ed3dSBarry Smith   PetscFunctionBegin;
159639f9d9dSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
160639f9d9dSBarry Smith 
161639f9d9dSBarry Smith   if (error != PETSC_DEFAULT) matfd->error_rel = error;
162639f9d9dSBarry Smith   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
1633a40ed3dSBarry Smith   PetscFunctionReturn(0);
164639f9d9dSBarry Smith }
165639f9d9dSBarry Smith 
166*4a2ae208SSatish Balay #undef __FUNCT__
167*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFrequency"
168005c665bSBarry Smith /*@
169e0907662SLois Curfman McInnes    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
170e0907662SLois Curfman McInnes    matrices.
171005c665bSBarry Smith 
172fee21e36SBarry Smith    Collective on MatFDColoring
173fee21e36SBarry Smith 
174ef5ee4d1SLois Curfman McInnes    Input Parameters:
175ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
176ef5ee4d1SLois Curfman McInnes -  freq - frequency (default is 1)
177ef5ee4d1SLois Curfman McInnes 
17815091d37SBarry Smith    Options Database Keys:
17915091d37SBarry Smith .  -mat_fd_coloring_freq <freq>  - Sets coloring frequency
18015091d37SBarry Smith 
18115091d37SBarry Smith    Level: advanced
18215091d37SBarry Smith 
183e0907662SLois Curfman McInnes    Notes:
184e0907662SLois Curfman McInnes    Using a modified Newton strategy, where the Jacobian remains fixed for several
185e0907662SLois Curfman McInnes    iterations, can be cost effective in terms of overall nonlinear solution
186e0907662SLois Curfman McInnes    efficiency.  This parameter indicates that a new Jacobian will be computed every
187e0907662SLois Curfman McInnes    <freq> nonlinear iterations.
188e0907662SLois Curfman McInnes 
189b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, frequency
190ef5ee4d1SLois Curfman McInnes 
19140964ad5SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency(), MatFDColoringSetRecompute()
192005c665bSBarry Smith @*/
193005c665bSBarry Smith int MatFDColoringSetFrequency(MatFDColoring matfd,int freq)
194005c665bSBarry Smith {
1953a40ed3dSBarry Smith   PetscFunctionBegin;
196005c665bSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
197005c665bSBarry Smith 
198005c665bSBarry Smith   matfd->freq = freq;
1993a40ed3dSBarry Smith   PetscFunctionReturn(0);
200005c665bSBarry Smith }
201005c665bSBarry Smith 
202*4a2ae208SSatish Balay #undef __FUNCT__
203*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringGetFrequency"
204ff0cfa39SBarry Smith /*@
205ff0cfa39SBarry Smith    MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian
206ff0cfa39SBarry Smith    matrices.
207ff0cfa39SBarry Smith 
208ef5ee4d1SLois Curfman McInnes    Not Collective
209ef5ee4d1SLois Curfman McInnes 
210ff0cfa39SBarry Smith    Input Parameters:
211ff0cfa39SBarry Smith .  coloring - the coloring context
212ff0cfa39SBarry Smith 
213ff0cfa39SBarry Smith    Output Parameters:
214ff0cfa39SBarry Smith .  freq - frequency (default is 1)
215ff0cfa39SBarry Smith 
21615091d37SBarry Smith    Options Database Keys:
21715091d37SBarry Smith .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
21815091d37SBarry Smith 
21915091d37SBarry Smith    Level: advanced
22015091d37SBarry Smith 
221ff0cfa39SBarry Smith    Notes:
222ff0cfa39SBarry Smith    Using a modified Newton strategy, where the Jacobian remains fixed for several
223ff0cfa39SBarry Smith    iterations, can be cost effective in terms of overall nonlinear solution
224ff0cfa39SBarry Smith    efficiency.  This parameter indicates that a new Jacobian will be computed every
225ff0cfa39SBarry Smith    <freq> nonlinear iterations.
226ff0cfa39SBarry Smith 
227ff0cfa39SBarry Smith .keywords: Mat, finite differences, coloring, get, frequency
228ef5ee4d1SLois Curfman McInnes 
229ef5ee4d1SLois Curfman McInnes .seealso: MatFDColoringSetFrequency()
230ff0cfa39SBarry Smith @*/
231ff0cfa39SBarry Smith int MatFDColoringGetFrequency(MatFDColoring matfd,int *freq)
232ff0cfa39SBarry Smith {
2333a40ed3dSBarry Smith   PetscFunctionBegin;
234ff0cfa39SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
235ff0cfa39SBarry Smith 
236ff0cfa39SBarry Smith   *freq = matfd->freq;
2373a40ed3dSBarry Smith   PetscFunctionReturn(0);
238ff0cfa39SBarry Smith }
239ff0cfa39SBarry Smith 
240*4a2ae208SSatish Balay #undef __FUNCT__
241*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFunction"
242d64ed03dSBarry Smith /*@C
243005c665bSBarry Smith    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
244005c665bSBarry Smith 
245fee21e36SBarry Smith    Collective on MatFDColoring
246fee21e36SBarry Smith 
247ef5ee4d1SLois Curfman McInnes    Input Parameters:
248ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
249ef5ee4d1SLois Curfman McInnes .  f - the function
250ef5ee4d1SLois Curfman McInnes -  fctx - the optional user-defined function context
251ef5ee4d1SLois Curfman McInnes 
25215091d37SBarry Smith    Level: intermediate
25315091d37SBarry Smith 
254f881d145SBarry Smith    Notes:
255f881d145SBarry Smith     In Fortran you must call MatFDColoringSetFunctionSNES() for a coloring object to
256f881d145SBarry Smith   be used with the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used
257f881d145SBarry Smith   with the TS solvers.
258f881d145SBarry Smith 
259b4fc646aSLois Curfman McInnes .keywords: Mat, Jacobian, finite differences, set, function
260005c665bSBarry Smith @*/
261840b8ebdSBarry Smith int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void),void *fctx)
262005c665bSBarry Smith {
2633a40ed3dSBarry Smith   PetscFunctionBegin;
264005c665bSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
265005c665bSBarry Smith 
266005c665bSBarry Smith   matfd->f    = f;
267005c665bSBarry Smith   matfd->fctx = fctx;
268005c665bSBarry Smith 
2693a40ed3dSBarry Smith   PetscFunctionReturn(0);
270005c665bSBarry Smith }
271005c665bSBarry Smith 
272*4a2ae208SSatish Balay #undef __FUNCT__
273*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFromOptions"
274639f9d9dSBarry Smith /*@
275b4fc646aSLois Curfman McInnes    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
276639f9d9dSBarry Smith    the options database.
277639f9d9dSBarry Smith 
278fee21e36SBarry Smith    Collective on MatFDColoring
279fee21e36SBarry Smith 
28065f2ba5bSLois Curfman McInnes    The Jacobian, F'(u), is estimated with the differencing approximation
281ef5ee4d1SLois Curfman McInnes .vb
28265f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
283f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
284f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
285ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
286ef5ee4d1SLois Curfman McInnes .ve
287ef5ee4d1SLois Curfman McInnes 
288ef5ee4d1SLois Curfman McInnes    Input Parameter:
289ef5ee4d1SLois Curfman McInnes .  coloring - the coloring context
290ef5ee4d1SLois Curfman McInnes 
291b4fc646aSLois Curfman McInnes    Options Database Keys:
292d15ffeeaSSatish Balay +  -mat_fd_coloring_err <err> - Sets <err> (square root
293ef5ee4d1SLois Curfman McInnes            of relative error in the function)
294f23b5b22SLois Curfman McInnes .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
295ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian
296ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view - Activates basic viewing
297ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view_info - Activates viewing info
298ef5ee4d1SLois Curfman McInnes -  -mat_fd_coloring_view_draw - Activates drawing
299639f9d9dSBarry Smith 
30015091d37SBarry Smith     Level: intermediate
30115091d37SBarry Smith 
302b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, parameters
303639f9d9dSBarry Smith @*/
304639f9d9dSBarry Smith int MatFDColoringSetFromOptions(MatFDColoring matfd)
305639f9d9dSBarry Smith {
306186905e3SBarry Smith   int        ierr;
3073a40ed3dSBarry Smith 
3083a40ed3dSBarry Smith   PetscFunctionBegin;
309639f9d9dSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
310639f9d9dSBarry Smith 
311b0a32e0cSBarry Smith   ierr = PetscOptionsBegin(matfd->comm,matfd->prefix,"Jacobian computation via finite differences option","MatFD");CHKERRQ(ierr);
312b0a32e0cSBarry Smith     ierr = PetscOptionsDouble("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
313b0a32e0cSBarry Smith     ierr = PetscOptionsDouble("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
314b0a32e0cSBarry Smith     ierr = PetscOptionsInt("-mat_fd_coloring_freq","How often Jacobian is recomputed","MatFDColoringSetFrequency",matfd->freq,&matfd->freq,0);CHKERRQ(ierr);
315186905e3SBarry Smith     /* not used here; but so they are presented in the GUI */
316b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view","Print entire datastructure used for Jacobian","None",0);CHKERRQ(ierr);
317b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view_info","Print number of colors etc for Jacobian","None",0);CHKERRQ(ierr);
318b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view_draw","Plot nonzero structure ofJacobian","None",0);CHKERRQ(ierr);
319b0a32e0cSBarry Smith   PetscOptionsEnd();CHKERRQ(ierr);
3203a40ed3dSBarry Smith   PetscFunctionReturn(0);
321005c665bSBarry Smith }
322005c665bSBarry Smith 
323*4a2ae208SSatish Balay #undef __FUNCT__
324*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Private"
325005c665bSBarry Smith int MatFDColoringView_Private(MatFDColoring fd)
326005c665bSBarry Smith {
327f1af5d2fSBarry Smith   int        ierr;
328f1af5d2fSBarry Smith   PetscTruth flg;
329005c665bSBarry Smith 
3303a40ed3dSBarry Smith   PetscFunctionBegin;
331b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr);
332005c665bSBarry Smith   if (flg) {
333b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
334005c665bSBarry Smith   }
335b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr);
336ae09f205SBarry Smith   if (flg) {
337fb9695e5SSatish Balay     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(fd->comm),PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
338b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
339b0a32e0cSBarry Smith     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
340ae09f205SBarry Smith   }
341b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr);
342005c665bSBarry Smith   if (flg) {
343b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
344b0a32e0cSBarry Smith     ierr = PetscViewerFlush(PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
345005c665bSBarry Smith   }
3463a40ed3dSBarry Smith   PetscFunctionReturn(0);
347bbf0e169SBarry Smith }
348bbf0e169SBarry Smith 
349*4a2ae208SSatish Balay #undef __FUNCT__
350*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringCreate"
351bbf0e169SBarry Smith /*@C
352639f9d9dSBarry Smith    MatFDColoringCreate - Creates a matrix coloring context for finite difference
353639f9d9dSBarry Smith    computation of Jacobians.
354bbf0e169SBarry Smith 
355ef5ee4d1SLois Curfman McInnes    Collective on Mat
356ef5ee4d1SLois Curfman McInnes 
357639f9d9dSBarry Smith    Input Parameters:
358ef5ee4d1SLois Curfman McInnes +  mat - the matrix containing the nonzero structure of the Jacobian
359ef5ee4d1SLois Curfman McInnes -  iscoloring - the coloring of the matrix
360bbf0e169SBarry Smith 
361bbf0e169SBarry Smith     Output Parameter:
362639f9d9dSBarry Smith .   color - the new coloring context
363bbf0e169SBarry Smith 
364b4fc646aSLois Curfman McInnes     Options Database Keys:
365ef5ee4d1SLois Curfman McInnes +    -mat_fd_coloring_view - Activates basic viewing or coloring
366ef5ee4d1SLois Curfman McInnes .    -mat_fd_coloring_view_draw - Activates drawing of coloring
367ef5ee4d1SLois Curfman McInnes -    -mat_fd_coloring_view_info - Activates viewing of coloring info
368639f9d9dSBarry Smith 
36915091d37SBarry Smith     Level: intermediate
37015091d37SBarry Smith 
3716831982aSBarry Smith .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
3726831982aSBarry Smith           MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
373bbf0e169SBarry Smith @*/
374639f9d9dSBarry Smith int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
375bbf0e169SBarry Smith {
376639f9d9dSBarry Smith   MatFDColoring c;
377639f9d9dSBarry Smith   MPI_Comm      comm;
378639f9d9dSBarry Smith   int           ierr,M,N;
379639f9d9dSBarry Smith 
3803a40ed3dSBarry Smith   PetscFunctionBegin;
381b0a32e0cSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
382639f9d9dSBarry Smith   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
38329bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Only for square matrices");
384639f9d9dSBarry Smith 
385f881d145SBarry Smith   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3869194eea9SBarry Smith   PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView);
387b0a32e0cSBarry Smith   PetscLogObjectCreate(c);
388639f9d9dSBarry Smith 
389f830108cSBarry Smith   if (mat->ops->fdcoloringcreate) {
390f830108cSBarry Smith     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
391639f9d9dSBarry Smith   } else {
39229bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Code not yet written for this matrix type");
393639f9d9dSBarry Smith   }
394639f9d9dSBarry Smith 
395639f9d9dSBarry Smith   c->error_rel         = 1.e-8;
396ae09f205SBarry Smith   c->umin              = 1.e-6;
397005c665bSBarry Smith   c->freq              = 1;
39840964ad5SBarry Smith   c->usersetsrecompute = PETSC_FALSE;
39940964ad5SBarry Smith   c->recompute         = PETSC_FALSE;
400005c665bSBarry Smith 
401005c665bSBarry Smith   ierr = MatFDColoringView_Private(c);CHKERRQ(ierr);
402639f9d9dSBarry Smith 
403639f9d9dSBarry Smith   *color = c;
404b0a32e0cSBarry Smith   ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
4053a40ed3dSBarry Smith   PetscFunctionReturn(0);
406bbf0e169SBarry Smith }
407bbf0e169SBarry Smith 
408*4a2ae208SSatish Balay #undef __FUNCT__
409*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringDestroy"
410bbf0e169SBarry Smith /*@C
411639f9d9dSBarry Smith     MatFDColoringDestroy - Destroys a matrix coloring context that was created
412639f9d9dSBarry Smith     via MatFDColoringCreate().
413bbf0e169SBarry Smith 
414ef5ee4d1SLois Curfman McInnes     Collective on MatFDColoring
415ef5ee4d1SLois Curfman McInnes 
416b4fc646aSLois Curfman McInnes     Input Parameter:
417639f9d9dSBarry Smith .   c - coloring context
418bbf0e169SBarry Smith 
41915091d37SBarry Smith     Level: intermediate
42015091d37SBarry Smith 
421639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
422bbf0e169SBarry Smith @*/
423639f9d9dSBarry Smith int MatFDColoringDestroy(MatFDColoring c)
424bbf0e169SBarry Smith {
425263760aaSBarry Smith   int i,ierr;
426bbf0e169SBarry Smith 
4273a40ed3dSBarry Smith   PetscFunctionBegin;
4283a40ed3dSBarry Smith   if (--c->refct > 0) PetscFunctionReturn(0);
429d4bb536fSBarry Smith 
430639f9d9dSBarry Smith   for (i=0; i<c->ncolors; i++) {
431606d414cSSatish Balay     if (c->columns[i])         {ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);}
432606d414cSSatish Balay     if (c->rows[i])            {ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);}
433606d414cSSatish Balay     if (c->columnsforrow[i])   {ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);}
43430b34957SBarry Smith     if (c->vscaleforrow && c->vscaleforrow[i]) {ierr = PetscFree(c->vscaleforrow[i]);CHKERRQ(ierr);}
435bbf0e169SBarry Smith   }
436606d414cSSatish Balay   ierr = PetscFree(c->ncolumns);CHKERRQ(ierr);
437606d414cSSatish Balay   ierr = PetscFree(c->columns);CHKERRQ(ierr);
438606d414cSSatish Balay   ierr = PetscFree(c->nrows);CHKERRQ(ierr);
439606d414cSSatish Balay   ierr = PetscFree(c->rows);CHKERRQ(ierr);
440606d414cSSatish Balay   ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr);
44130b34957SBarry Smith   if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);}
4424f113abfSBarry Smith   if (c->vscale)       {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);}
443005c665bSBarry Smith   if (c->w1) {
444005c665bSBarry Smith     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
445005c665bSBarry Smith     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
446005c665bSBarry Smith     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
447005c665bSBarry Smith   }
448b0a32e0cSBarry Smith   PetscLogObjectDestroy(c);
449639f9d9dSBarry Smith   PetscHeaderDestroy(c);
4503a40ed3dSBarry Smith   PetscFunctionReturn(0);
451bbf0e169SBarry Smith }
45243a90d84SBarry Smith 
453*4a2ae208SSatish Balay #undef __FUNCT__
454*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApply"
45543a90d84SBarry Smith /*@
456e0907662SLois Curfman McInnes     MatFDColoringApply - Given a matrix for which a MatFDColoring context
457e0907662SLois Curfman McInnes     has been created, computes the Jacobian for a function via finite differences.
45843a90d84SBarry Smith 
459fee21e36SBarry Smith     Collective on MatFDColoring
460fee21e36SBarry Smith 
461ef5ee4d1SLois Curfman McInnes     Input Parameters:
462ef5ee4d1SLois Curfman McInnes +   mat - location to store Jacobian
463ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
464ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
465ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
466ef5ee4d1SLois Curfman McInnes 
4678bba8e72SBarry Smith    Options Database Keys:
468ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
4698bba8e72SBarry Smith 
47015091d37SBarry Smith    Level: intermediate
47115091d37SBarry Smith 
47243a90d84SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
47343a90d84SBarry Smith 
47443a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences
47543a90d84SBarry Smith @*/
476005c665bSBarry Smith int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
47743a90d84SBarry Smith {
4785904e1b1SBarry Smith   int           (*f)(void *,Vec,Vec,void*) = (int (*)(void *,Vec,Vec,void *))coloring->f;
4795904e1b1SBarry Smith   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow;
4805904e1b1SBarry Smith   Scalar        dx,mone = -1.0,*y,*xx,*w3_array;
4814f113abfSBarry Smith   Scalar        *vscale_array;
482329f5518SBarry Smith   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
483005c665bSBarry Smith   Vec           w1,w2,w3;
484005c665bSBarry Smith   void          *fctx = coloring->fctx;
485f1af5d2fSBarry Smith   PetscTruth    flg;
486005c665bSBarry Smith 
487a2e34c3dSBarry Smith 
4883a40ed3dSBarry Smith   PetscFunctionBegin;
489e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(J,MAT_COOKIE);
490e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
491e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(x1,VEC_COOKIE);
492e0907662SLois Curfman McInnes 
49340964ad5SBarry Smith   if (coloring->usersetsrecompute) {
49440964ad5SBarry Smith     if (!coloring->recompute) {
49540964ad5SBarry Smith       *flag = SAME_PRECONDITIONER;
49640964ad5SBarry Smith       PetscFunctionReturn(0);
49740964ad5SBarry Smith     } else {
49840964ad5SBarry Smith       coloring->recompute = PETSC_FALSE;
49940964ad5SBarry Smith     }
50040964ad5SBarry Smith   }
50140964ad5SBarry Smith 
502b0a32e0cSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
503005c665bSBarry Smith   if (!coloring->w1) {
504005c665bSBarry Smith     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
505b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w1);
506005c665bSBarry Smith     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
507b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w2);
508005c665bSBarry Smith     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
509b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w3);
510005c665bSBarry Smith   }
511005c665bSBarry Smith   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
51243a90d84SBarry Smith 
5134c49b128SBarry Smith   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
514b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
515f1af5d2fSBarry Smith   if (flg) {
516b0a32e0cSBarry Smith     PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
517e0907662SLois Curfman McInnes   } else {
51843a90d84SBarry Smith     ierr = MatZeroEntries(J);CHKERRQ(ierr);
519e0907662SLois Curfman McInnes   }
52043a90d84SBarry Smith 
52143a90d84SBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
52243a90d84SBarry Smith   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
52343a90d84SBarry Smith   ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
52443a90d84SBarry Smith 
52543a90d84SBarry Smith   /*
5269782cf98SBarry Smith       Compute all the scale factors and share with other processors
5279782cf98SBarry Smith   */
5289782cf98SBarry Smith   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
5294f113abfSBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
5309782cf98SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
5319782cf98SBarry Smith     /*
5329782cf98SBarry Smith        Loop over each column associated with color adding the
5339782cf98SBarry Smith        perturbation to the vector w3.
5349782cf98SBarry Smith     */
5359782cf98SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
5369782cf98SBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
5379782cf98SBarry Smith       dx  = xx[col];
5389782cf98SBarry Smith       if (dx == 0.0) dx = 1.0;
5399782cf98SBarry Smith #if !defined(PETSC_USE_COMPLEX)
5409782cf98SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
5419782cf98SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
5429782cf98SBarry Smith #else
5439782cf98SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
5449782cf98SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
5459782cf98SBarry Smith #endif
5469782cf98SBarry Smith       dx                *= epsilon;
54730b34957SBarry Smith       vscale_array[col] = 1.0/dx;
5489782cf98SBarry Smith     }
5499782cf98SBarry Smith   }
550a2e34c3dSBarry Smith   vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
55130b34957SBarry Smith   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
55230b34957SBarry Smith   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5539782cf98SBarry Smith 
554ce1411ecSBarry Smith   /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
555ce1411ecSBarry Smith       ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
556b0a32e0cSBarry Smith 
55730b34957SBarry Smith   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
55830b34957SBarry Smith   else                        vscaleforrow = coloring->columnsforrow;
55930b34957SBarry Smith 
56030b34957SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
5619782cf98SBarry Smith   /*
56243a90d84SBarry Smith       Loop over each color
56343a90d84SBarry Smith   */
56443a90d84SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
56543a90d84SBarry Smith     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
56642460c72SBarry Smith     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
56743a90d84SBarry Smith     /*
56843a90d84SBarry Smith        Loop over each column associated with color adding the
56943a90d84SBarry Smith        perturbation to the vector w3.
57043a90d84SBarry Smith     */
57143a90d84SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
57243a90d84SBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
57342460c72SBarry Smith       dx  = xx[col];
574ae09f205SBarry Smith       if (dx == 0.0) dx = 1.0;
575aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
576ae09f205SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
577ae09f205SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
57843a90d84SBarry Smith #else
579329f5518SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
580329f5518SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
58143a90d84SBarry Smith #endif
58243a90d84SBarry Smith       dx            *= epsilon;
58329bbc08cSBarry Smith       if (!PetscAbsScalar(dx)) SETERRQ(1,"Computed 0 differencing parameter");
58442460c72SBarry Smith       w3_array[col] += dx;
58543a90d84SBarry Smith     }
58642460c72SBarry Smith     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
5873b28642cSBarry Smith 
58843a90d84SBarry Smith     /*
589e0907662SLois Curfman McInnes        Evaluate function at x1 + dx (here dx is a vector of perturbations)
59043a90d84SBarry Smith     */
591a2e34c3dSBarry Smith 
59243a90d84SBarry Smith     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
59343a90d84SBarry Smith     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
5949782cf98SBarry Smith 
59543a90d84SBarry Smith     /*
596e0907662SLois Curfman McInnes        Loop over rows of vector, putting results into Jacobian matrix
59743a90d84SBarry Smith     */
5983b28642cSBarry Smith     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
59943a90d84SBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
60043a90d84SBarry Smith       row    = coloring->rows[k][l];
60143a90d84SBarry Smith       col    = coloring->columnsforrow[k][l];
6025904e1b1SBarry Smith       y[row] *= vscale_array[vscaleforrow[k][l]];
60343a90d84SBarry Smith       srow   = row + start;
60443a90d84SBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
60543a90d84SBarry Smith     }
6063b28642cSBarry Smith     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
60743a90d84SBarry Smith   }
60830b34957SBarry Smith   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
60942460c72SBarry Smith   xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
61043a90d84SBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
61143a90d84SBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
612b0a32e0cSBarry Smith   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
613a2e34c3dSBarry Smith 
614b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test",&flg);CHKERRQ(ierr);
615a2e34c3dSBarry Smith   if (flg) {
616a2e34c3dSBarry Smith     ierr = MatNullSpaceTest(J->nullsp,J);CHKERRQ(ierr);
617a2e34c3dSBarry Smith   }
6183a40ed3dSBarry Smith   PetscFunctionReturn(0);
61943a90d84SBarry Smith }
620840b8ebdSBarry Smith 
621*4a2ae208SSatish Balay #undef __FUNCT__
622*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApplyTS"
623840b8ebdSBarry Smith /*@
624840b8ebdSBarry Smith     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
625840b8ebdSBarry Smith     has been created, computes the Jacobian for a function via finite differences.
626840b8ebdSBarry Smith 
627fee21e36SBarry Smith    Collective on Mat, MatFDColoring, and Vec
628fee21e36SBarry Smith 
629ef5ee4d1SLois Curfman McInnes     Input Parameters:
6303b28642cSBarry Smith +   mat - location to store Jacobian
631ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
632ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
633ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
634ef5ee4d1SLois Curfman McInnes 
635840b8ebdSBarry Smith    Options Database Keys:
636ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
637840b8ebdSBarry Smith 
63815091d37SBarry Smith    Level: intermediate
63915091d37SBarry Smith 
640840b8ebdSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
641840b8ebdSBarry Smith 
642840b8ebdSBarry Smith .keywords: coloring, Jacobian, finite differences
643840b8ebdSBarry Smith @*/
644329f5518SBarry Smith int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
645840b8ebdSBarry Smith {
646329f5518SBarry Smith   int           (*f)(void *,PetscReal,Vec,Vec,void*)=(int (*)(void *,PetscReal,Vec,Vec,void *))coloring->f;
6475904e1b1SBarry Smith   int           k,ierr,N,start,end,l,row,col,srow,**vscaleforrow;
6485904e1b1SBarry Smith   Scalar        dx,mone = -1.0,*y,*xx,*w3_array;
6495904e1b1SBarry Smith   Scalar        *vscale_array;
650329f5518SBarry Smith   PetscReal     epsilon = coloring->error_rel,umin = coloring->umin;
651840b8ebdSBarry Smith   Vec           w1,w2,w3;
652840b8ebdSBarry Smith   void          *fctx = coloring->fctx;
653f1af5d2fSBarry Smith   PetscTruth    flg;
654840b8ebdSBarry Smith 
6553a40ed3dSBarry Smith   PetscFunctionBegin;
656840b8ebdSBarry Smith   PetscValidHeaderSpecific(J,MAT_COOKIE);
657840b8ebdSBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
658840b8ebdSBarry Smith   PetscValidHeaderSpecific(x1,VEC_COOKIE);
659840b8ebdSBarry Smith 
660b0a32e0cSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
661840b8ebdSBarry Smith   if (!coloring->w1) {
662840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
663b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w1);
664840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
665b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w2);
666840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
667b0a32e0cSBarry Smith     PetscLogObjectParent(coloring,coloring->w3);
668840b8ebdSBarry Smith   }
669840b8ebdSBarry Smith   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
670840b8ebdSBarry Smith 
6715904e1b1SBarry Smith   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
672b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
673f1af5d2fSBarry Smith   if (flg) {
674b0a32e0cSBarry Smith     PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
675840b8ebdSBarry Smith   } else {
676840b8ebdSBarry Smith     ierr = MatZeroEntries(J);CHKERRQ(ierr);
677840b8ebdSBarry Smith   }
678840b8ebdSBarry Smith 
679840b8ebdSBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
680840b8ebdSBarry Smith   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
681840b8ebdSBarry Smith   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
682840b8ebdSBarry Smith 
683840b8ebdSBarry Smith   /*
6845904e1b1SBarry Smith       Compute all the scale factors and share with other processors
685840b8ebdSBarry Smith   */
6865904e1b1SBarry Smith   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
6875904e1b1SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
688840b8ebdSBarry Smith   for (k=0; k<coloring->ncolors; k++) {
689840b8ebdSBarry Smith     /*
690840b8ebdSBarry Smith        Loop over each column associated with color adding the
691840b8ebdSBarry Smith        perturbation to the vector w3.
692840b8ebdSBarry Smith     */
693840b8ebdSBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
694840b8ebdSBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
6955904e1b1SBarry Smith       dx  = xx[col];
696840b8ebdSBarry Smith       if (dx == 0.0) dx = 1.0;
697aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
698840b8ebdSBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
699840b8ebdSBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
700840b8ebdSBarry Smith #else
701329f5518SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
702329f5518SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
703840b8ebdSBarry Smith #endif
704840b8ebdSBarry Smith       dx                *= epsilon;
7055904e1b1SBarry Smith       vscale_array[col] = 1.0/dx;
706840b8ebdSBarry Smith     }
7075904e1b1SBarry Smith   }
7085904e1b1SBarry Smith   vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
7095904e1b1SBarry Smith   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7105904e1b1SBarry Smith   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7115904e1b1SBarry Smith 
7125904e1b1SBarry Smith   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
7135904e1b1SBarry Smith   else                        vscaleforrow = coloring->columnsforrow;
7145904e1b1SBarry Smith 
7155904e1b1SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
7165904e1b1SBarry Smith   /*
7175904e1b1SBarry Smith       Loop over each color
7185904e1b1SBarry Smith   */
7195904e1b1SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
7205904e1b1SBarry Smith     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
7215904e1b1SBarry Smith     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
7225904e1b1SBarry Smith     /*
7235904e1b1SBarry Smith        Loop over each column associated with color adding the
7245904e1b1SBarry Smith        perturbation to the vector w3.
7255904e1b1SBarry Smith     */
7265904e1b1SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
7275904e1b1SBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
7285904e1b1SBarry Smith       dx  = xx[col];
7295904e1b1SBarry Smith       if (dx == 0.0) dx = 1.0;
7305904e1b1SBarry Smith #if !defined(PETSC_USE_COMPLEX)
7315904e1b1SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
7325904e1b1SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
7335904e1b1SBarry Smith #else
7345904e1b1SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
7355904e1b1SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
7365904e1b1SBarry Smith #endif
7375904e1b1SBarry Smith       dx            *= epsilon;
7385904e1b1SBarry Smith       w3_array[col] += dx;
7395904e1b1SBarry Smith     }
7405904e1b1SBarry Smith     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
7415904e1b1SBarry Smith 
742840b8ebdSBarry Smith     /*
743840b8ebdSBarry Smith        Evaluate function at x1 + dx (here dx is a vector of perturbations)
744840b8ebdSBarry Smith     */
745840b8ebdSBarry Smith     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
746840b8ebdSBarry Smith     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
7475904e1b1SBarry Smith 
748840b8ebdSBarry Smith     /*
749840b8ebdSBarry Smith        Loop over rows of vector, putting results into Jacobian matrix
750840b8ebdSBarry Smith     */
7513b28642cSBarry Smith     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
752840b8ebdSBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
753840b8ebdSBarry Smith       row    = coloring->rows[k][l];
754840b8ebdSBarry Smith       col    = coloring->columnsforrow[k][l];
7555904e1b1SBarry Smith       y[row] *= vscale_array[vscaleforrow[k][l]];
756840b8ebdSBarry Smith       srow   = row + start;
757840b8ebdSBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
758840b8ebdSBarry Smith     }
7593b28642cSBarry Smith     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
760840b8ebdSBarry Smith   }
7615904e1b1SBarry Smith   ierr  = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
7625904e1b1SBarry Smith   xx    = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
763840b8ebdSBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
764840b8ebdSBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
765b0a32e0cSBarry Smith   ierr  = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
7663a40ed3dSBarry Smith   PetscFunctionReturn(0);
767840b8ebdSBarry Smith }
7683b28642cSBarry Smith 
7693b28642cSBarry Smith 
770*4a2ae208SSatish Balay #undef __FUNCT__
771*4a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetRecompute()"
77240964ad5SBarry Smith /*@C
77340964ad5SBarry Smith    MatFDColoringSetRecompute - Indicates that the next time a Jacobian preconditioner
77440964ad5SBarry Smith      is needed it sholuld be recomputed. Once this is called and the new Jacobian is computed
77540964ad5SBarry Smith      no additional Jacobian's will be computed (the same one will be used) until this is
77640964ad5SBarry Smith      called again.
77740964ad5SBarry Smith 
77840964ad5SBarry Smith    Collective on MatFDColoring
77940964ad5SBarry Smith 
78040964ad5SBarry Smith    Input  Parameters:
78140964ad5SBarry Smith .  c - the coloring context
78240964ad5SBarry Smith 
78340964ad5SBarry Smith    Level: intermediate
78440964ad5SBarry Smith 
78540964ad5SBarry Smith    Notes: The MatFDColoringSetFrequency() is ignored once this is called
78640964ad5SBarry Smith 
78740964ad5SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringSetFrequency()
78840964ad5SBarry Smith 
78940964ad5SBarry Smith .keywords: Mat, finite differences, coloring
79040964ad5SBarry Smith @*/
79140964ad5SBarry Smith int MatFDColoringSetRecompute(MatFDColoring c)
79240964ad5SBarry Smith {
79340964ad5SBarry Smith   PetscFunctionBegin;
79440964ad5SBarry Smith   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
79540964ad5SBarry Smith   c->usersetsrecompute = PETSC_TRUE;
79640964ad5SBarry Smith   c->recompute         = PETSC_TRUE;
79740964ad5SBarry Smith   PetscFunctionReturn(0);
79840964ad5SBarry Smith }
79940964ad5SBarry Smith 
8003b28642cSBarry Smith 
801