xref: /petsc/src/mat/matfd/fdmatrix.c (revision 52e6d16ba989af9362d0fcebb12e73dd7c9666ed)
1bbf0e169SBarry Smith /*
2639f9d9dSBarry Smith    This is where the abstract matrix operations are defined that are
3639f9d9dSBarry Smith   used for finite difference computations of Jacobians using coloring.
4bbf0e169SBarry Smith */
5bbf0e169SBarry Smith 
6e090d566SSatish Balay #include "src/mat/matimpl.h"        /*I "petscmat.h" I*/
7bbf0e169SBarry Smith 
88ba1e511SMatthew Knepley /* Logging support */
96849ba73SBarry Smith PetscCookie MAT_FDCOLORING_COOKIE = 0;
108ba1e511SMatthew Knepley 
114a2ae208SSatish Balay #undef __FUNCT__
123a7fca6bSBarry Smith #define __FUNCT__ "MatFDColoringSetF"
13dfbe8321SBarry Smith PetscErrorCode 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"
226849ba73SBarry Smith static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
239194eea9SBarry Smith {
249194eea9SBarry Smith   MatFDColoring  fd = (MatFDColoring)Aa;
25dfbe8321SBarry Smith   PetscErrorCode ierr;
2638baddfdSBarry Smith   PetscInt       i,j;
279194eea9SBarry Smith   PetscReal      x,y;
289194eea9SBarry Smith 
299194eea9SBarry Smith   PetscFunctionBegin;
309194eea9SBarry Smith 
319194eea9SBarry Smith   /* loop over colors  */
329194eea9SBarry Smith   for (i=0; i<fd->ncolors; i++) {
339194eea9SBarry Smith     for (j=0; j<fd->nrows[i]; j++) {
349194eea9SBarry Smith       y = fd->M - fd->rows[i][j] - fd->rstart;
359194eea9SBarry Smith       x = fd->columnsforrow[i][j];
36b0a32e0cSBarry Smith       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
379194eea9SBarry Smith     }
389194eea9SBarry Smith   }
399194eea9SBarry Smith   PetscFunctionReturn(0);
409194eea9SBarry Smith }
419194eea9SBarry Smith 
424a2ae208SSatish Balay #undef __FUNCT__
434a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw"
446849ba73SBarry Smith static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
45005c665bSBarry Smith {
46dfbe8321SBarry Smith   PetscErrorCode ierr;
47005c665bSBarry Smith   PetscTruth     isnull;
48b0a32e0cSBarry Smith   PetscDraw      draw;
4954d96fa3SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
50005c665bSBarry Smith 
513a40ed3dSBarry Smith   PetscFunctionBegin;
52b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
53b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
549194eea9SBarry Smith 
559194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
56005c665bSBarry Smith 
57005c665bSBarry Smith   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
58005c665bSBarry Smith   xr += w;     yr += h;    xl = -w;     yl = -h;
59b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
60b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
619194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
623a40ed3dSBarry Smith   PetscFunctionReturn(0);
63005c665bSBarry Smith }
64005c665bSBarry Smith 
654a2ae208SSatish Balay #undef __FUNCT__
664a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView"
67bbf0e169SBarry Smith /*@C
68639f9d9dSBarry Smith    MatFDColoringView - Views a finite difference coloring context.
69bbf0e169SBarry Smith 
704c49b128SBarry Smith    Collective on MatFDColoring
71fee21e36SBarry Smith 
72ef5ee4d1SLois Curfman McInnes    Input  Parameters:
73ef5ee4d1SLois Curfman McInnes +  c - the coloring context
74ef5ee4d1SLois Curfman McInnes -  viewer - visualization context
75ef5ee4d1SLois Curfman McInnes 
7615091d37SBarry Smith    Level: intermediate
7715091d37SBarry Smith 
78b4fc646aSLois Curfman McInnes    Notes:
79b4fc646aSLois Curfman McInnes    The available visualization contexts include
80b0a32e0cSBarry Smith +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
81b0a32e0cSBarry Smith .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
82ef5ee4d1SLois Curfman McInnes         output where only the first processor opens
83ef5ee4d1SLois Curfman McInnes         the file.  All other processors send their
84ef5ee4d1SLois Curfman McInnes         data to the first processor to print.
85b0a32e0cSBarry Smith -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
86bbf0e169SBarry Smith 
879194eea9SBarry Smith    Notes:
889194eea9SBarry Smith      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
89b0a32e0cSBarry Smith    involves more than 33 then some seemingly identical colors are displayed making it look
909194eea9SBarry Smith    like an illegal coloring. This is just a graphical artifact.
919194eea9SBarry Smith 
92639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
93005c665bSBarry Smith 
94b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, view
95bbf0e169SBarry Smith @*/
96dfbe8321SBarry Smith PetscErrorCode MatFDColoringView(MatFDColoring c,PetscViewer viewer)
97bbf0e169SBarry Smith {
986849ba73SBarry Smith   PetscErrorCode    ierr;
9938baddfdSBarry Smith   PetscInt          i,j;
10032077d6dSBarry Smith   PetscTruth        isdraw,iascii;
101f3ef73ceSBarry Smith   PetscViewerFormat format;
102bbf0e169SBarry Smith 
1033a40ed3dSBarry Smith   PetscFunctionBegin;
1044482741eSBarry Smith   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE,1);
105b0a32e0cSBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(c->comm);
1064482741eSBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2);
107c9780b6fSBarry Smith   PetscCheckSameComm(c,1,viewer,2);
108bbf0e169SBarry Smith 
109fb9695e5SSatish Balay   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
11032077d6dSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
1110f5bd95cSBarry Smith   if (isdraw) {
112b4fc646aSLois Curfman McInnes     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
11332077d6dSBarry Smith   } else if (iascii) {
114b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"MatFDColoring Object:\n");CHKERRQ(ierr);
115b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%g\n",c->error_rel);CHKERRQ(ierr);
116b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%g\n",c->umin);CHKERRQ(ierr);
11777431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);CHKERRQ(ierr);
118ae09f205SBarry Smith 
119b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
120fb9695e5SSatish Balay     if (format != PETSC_VIEWER_ASCII_INFO) {
121b4fc646aSLois Curfman McInnes       for (i=0; i<c->ncolors; i++) {
12277431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);CHKERRQ(ierr);
12377431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr);
124b4fc646aSLois Curfman McInnes         for (j=0; j<c->ncolumns[i]; j++) {
12577431f27SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);CHKERRQ(ierr);
126639f9d9dSBarry Smith         }
12777431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr);
128b4fc646aSLois Curfman McInnes         for (j=0; j<c->nrows[i]; j++) {
12977431f27SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %D %D \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
130b4fc646aSLois Curfman McInnes         }
131bbf0e169SBarry Smith       }
132bbf0e169SBarry Smith     }
133b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1345cd90555SBarry Smith   } else {
13579a5c55eSBarry Smith     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
136bbf0e169SBarry Smith   }
1373a40ed3dSBarry Smith   PetscFunctionReturn(0);
138639f9d9dSBarry Smith }
139639f9d9dSBarry Smith 
1404a2ae208SSatish Balay #undef __FUNCT__
1414a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetParameters"
142639f9d9dSBarry Smith /*@
143b4fc646aSLois Curfman McInnes    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
144b4fc646aSLois Curfman McInnes    a Jacobian matrix using finite differences.
145639f9d9dSBarry Smith 
146ef5ee4d1SLois Curfman McInnes    Collective on MatFDColoring
147ef5ee4d1SLois Curfman McInnes 
148ef5ee4d1SLois Curfman McInnes    The Jacobian is estimated with the differencing approximation
149ef5ee4d1SLois Curfman McInnes .vb
15065f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
151f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
152f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
153ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
154ef5ee4d1SLois Curfman McInnes .ve
155639f9d9dSBarry Smith 
156639f9d9dSBarry Smith    Input Parameters:
157ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
158639f9d9dSBarry Smith .  error_rel - relative error
159f23b5b22SLois Curfman McInnes -  umin - minimum allowable u-value magnitude
160fee21e36SBarry Smith 
16115091d37SBarry Smith    Level: advanced
16215091d37SBarry Smith 
163b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, parameters
164b4fc646aSLois Curfman McInnes 
165b4fc646aSLois Curfman McInnes .seealso: MatFDColoringCreate()
166639f9d9dSBarry Smith @*/
167dfbe8321SBarry Smith PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
168639f9d9dSBarry Smith {
1693a40ed3dSBarry Smith   PetscFunctionBegin;
1704482741eSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
171639f9d9dSBarry Smith 
172639f9d9dSBarry Smith   if (error != PETSC_DEFAULT) matfd->error_rel = error;
173639f9d9dSBarry Smith   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
1743a40ed3dSBarry Smith   PetscFunctionReturn(0);
175639f9d9dSBarry Smith }
176639f9d9dSBarry Smith 
1774a2ae208SSatish Balay #undef __FUNCT__
1784a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFrequency"
179005c665bSBarry Smith /*@
180e0907662SLois Curfman McInnes    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
181e0907662SLois Curfman McInnes    matrices.
182005c665bSBarry Smith 
183fee21e36SBarry Smith    Collective on MatFDColoring
184fee21e36SBarry Smith 
185ef5ee4d1SLois Curfman McInnes    Input Parameters:
186ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
187ef5ee4d1SLois Curfman McInnes -  freq - frequency (default is 1)
188ef5ee4d1SLois Curfman McInnes 
18915091d37SBarry Smith    Options Database Keys:
19015091d37SBarry Smith .  -mat_fd_coloring_freq <freq>  - Sets coloring frequency
19115091d37SBarry Smith 
19215091d37SBarry Smith    Level: advanced
19315091d37SBarry Smith 
194e0907662SLois Curfman McInnes    Notes:
195e0907662SLois Curfman McInnes    Using a modified Newton strategy, where the Jacobian remains fixed for several
196e0907662SLois Curfman McInnes    iterations, can be cost effective in terms of overall nonlinear solution
197e0907662SLois Curfman McInnes    efficiency.  This parameter indicates that a new Jacobian will be computed every
198e0907662SLois Curfman McInnes    <freq> nonlinear iterations.
199e0907662SLois Curfman McInnes 
200b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, frequency
201ef5ee4d1SLois Curfman McInnes 
20240964ad5SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency(), MatFDColoringSetRecompute()
203005c665bSBarry Smith @*/
20438baddfdSBarry Smith PetscErrorCode MatFDColoringSetFrequency(MatFDColoring matfd,PetscInt freq)
205005c665bSBarry Smith {
2063a40ed3dSBarry Smith   PetscFunctionBegin;
2074482741eSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
208005c665bSBarry Smith 
209005c665bSBarry Smith   matfd->freq = freq;
2103a40ed3dSBarry Smith   PetscFunctionReturn(0);
211005c665bSBarry Smith }
212005c665bSBarry Smith 
2134a2ae208SSatish Balay #undef __FUNCT__
2144a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringGetFrequency"
215ff0cfa39SBarry Smith /*@
216ff0cfa39SBarry Smith    MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian
217ff0cfa39SBarry Smith    matrices.
218ff0cfa39SBarry Smith 
219ef5ee4d1SLois Curfman McInnes    Not Collective
220ef5ee4d1SLois Curfman McInnes 
221ff0cfa39SBarry Smith    Input Parameters:
222ff0cfa39SBarry Smith .  coloring - the coloring context
223ff0cfa39SBarry Smith 
224ff0cfa39SBarry Smith    Output Parameters:
225ff0cfa39SBarry Smith .  freq - frequency (default is 1)
226ff0cfa39SBarry Smith 
22715091d37SBarry Smith    Options Database Keys:
22815091d37SBarry Smith .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
22915091d37SBarry Smith 
23015091d37SBarry Smith    Level: advanced
23115091d37SBarry Smith 
232ff0cfa39SBarry Smith    Notes:
233ff0cfa39SBarry Smith    Using a modified Newton strategy, where the Jacobian remains fixed for several
234ff0cfa39SBarry Smith    iterations, can be cost effective in terms of overall nonlinear solution
235ff0cfa39SBarry Smith    efficiency.  This parameter indicates that a new Jacobian will be computed every
236ff0cfa39SBarry Smith    <freq> nonlinear iterations.
237ff0cfa39SBarry Smith 
238ff0cfa39SBarry Smith .keywords: Mat, finite differences, coloring, get, frequency
239ef5ee4d1SLois Curfman McInnes 
240ef5ee4d1SLois Curfman McInnes .seealso: MatFDColoringSetFrequency()
241ff0cfa39SBarry Smith @*/
24238baddfdSBarry Smith PetscErrorCode MatFDColoringGetFrequency(MatFDColoring matfd,PetscInt *freq)
243ff0cfa39SBarry Smith {
2443a40ed3dSBarry Smith   PetscFunctionBegin;
2454482741eSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
246ff0cfa39SBarry Smith   *freq = matfd->freq;
2473a40ed3dSBarry Smith   PetscFunctionReturn(0);
248ff0cfa39SBarry Smith }
249ff0cfa39SBarry Smith 
2504a2ae208SSatish Balay #undef __FUNCT__
2514a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFunction"
252d64ed03dSBarry Smith /*@C
253005c665bSBarry Smith    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
254005c665bSBarry Smith 
255fee21e36SBarry Smith    Collective on MatFDColoring
256fee21e36SBarry Smith 
257ef5ee4d1SLois Curfman McInnes    Input Parameters:
258ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
259ef5ee4d1SLois Curfman McInnes .  f - the function
260ef5ee4d1SLois Curfman McInnes -  fctx - the optional user-defined function context
261ef5ee4d1SLois Curfman McInnes 
26215091d37SBarry Smith    Level: intermediate
26315091d37SBarry Smith 
264f881d145SBarry Smith    Notes:
265f881d145SBarry Smith     In Fortran you must call MatFDColoringSetFunctionSNES() for a coloring object to
266f881d145SBarry Smith   be used with the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used
267f881d145SBarry Smith   with the TS solvers.
268f881d145SBarry Smith 
269b4fc646aSLois Curfman McInnes .keywords: Mat, Jacobian, finite differences, set, function
270005c665bSBarry Smith @*/
2716849ba73SBarry Smith PetscErrorCode MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
272005c665bSBarry Smith {
2733a40ed3dSBarry Smith   PetscFunctionBegin;
2744482741eSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
275005c665bSBarry Smith   matfd->f    = f;
276005c665bSBarry Smith   matfd->fctx = fctx;
2773a40ed3dSBarry Smith   PetscFunctionReturn(0);
278005c665bSBarry Smith }
279005c665bSBarry Smith 
2804a2ae208SSatish Balay #undef __FUNCT__
2814a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFromOptions"
282639f9d9dSBarry Smith /*@
283b4fc646aSLois Curfman McInnes    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
284639f9d9dSBarry Smith    the options database.
285639f9d9dSBarry Smith 
286fee21e36SBarry Smith    Collective on MatFDColoring
287fee21e36SBarry Smith 
28865f2ba5bSLois Curfman McInnes    The Jacobian, F'(u), is estimated with the differencing approximation
289ef5ee4d1SLois Curfman McInnes .vb
29065f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
291f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
292f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
293ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
294ef5ee4d1SLois Curfman McInnes .ve
295ef5ee4d1SLois Curfman McInnes 
296ef5ee4d1SLois Curfman McInnes    Input Parameter:
297ef5ee4d1SLois Curfman McInnes .  coloring - the coloring context
298ef5ee4d1SLois Curfman McInnes 
299b4fc646aSLois Curfman McInnes    Options Database Keys:
300d15ffeeaSSatish Balay +  -mat_fd_coloring_err <err> - Sets <err> (square root
301ef5ee4d1SLois Curfman McInnes            of relative error in the function)
302f23b5b22SLois Curfman McInnes .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
303ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian
304ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view - Activates basic viewing
305ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view_info - Activates viewing info
306ef5ee4d1SLois Curfman McInnes -  -mat_fd_coloring_view_draw - Activates drawing
307639f9d9dSBarry Smith 
30815091d37SBarry Smith     Level: intermediate
30915091d37SBarry Smith 
310b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, parameters
311d1c39f55SBarry Smith 
312d1c39f55SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
313d1c39f55SBarry Smith 
314639f9d9dSBarry Smith @*/
315dfbe8321SBarry Smith PetscErrorCode MatFDColoringSetFromOptions(MatFDColoring matfd)
316639f9d9dSBarry Smith {
317dfbe8321SBarry Smith   PetscErrorCode ierr;
3183a40ed3dSBarry Smith 
3193a40ed3dSBarry Smith   PetscFunctionBegin;
3204482741eSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE,1);
321639f9d9dSBarry Smith 
322b0a32e0cSBarry Smith   ierr = PetscOptionsBegin(matfd->comm,matfd->prefix,"Jacobian computation via finite differences option","MatFD");CHKERRQ(ierr);
32387828ca2SBarry Smith     ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
32487828ca2SBarry Smith     ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
325b0a32e0cSBarry Smith     ierr = PetscOptionsInt("-mat_fd_coloring_freq","How often Jacobian is recomputed","MatFDColoringSetFrequency",matfd->freq,&matfd->freq,0);CHKERRQ(ierr);
326186905e3SBarry Smith     /* not used here; but so they are presented in the GUI */
327b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view","Print entire datastructure used for Jacobian","None",0);CHKERRQ(ierr);
328b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view_info","Print number of colors etc for Jacobian","None",0);CHKERRQ(ierr);
329b0a32e0cSBarry Smith     ierr = PetscOptionsName("-mat_fd_coloring_view_draw","Plot nonzero structure ofJacobian","None",0);CHKERRQ(ierr);
330b0a32e0cSBarry Smith   PetscOptionsEnd();CHKERRQ(ierr);
3313a40ed3dSBarry Smith   PetscFunctionReturn(0);
332005c665bSBarry Smith }
333005c665bSBarry Smith 
3344a2ae208SSatish Balay #undef __FUNCT__
3354a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Private"
336dfbe8321SBarry Smith PetscErrorCode MatFDColoringView_Private(MatFDColoring fd)
337005c665bSBarry Smith {
338dfbe8321SBarry Smith   PetscErrorCode ierr;
339f1af5d2fSBarry Smith   PetscTruth     flg;
340005c665bSBarry Smith 
3413a40ed3dSBarry Smith   PetscFunctionBegin;
342b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg);CHKERRQ(ierr);
343005c665bSBarry Smith   if (flg) {
344b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
345005c665bSBarry Smith   }
346b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg);CHKERRQ(ierr);
347ae09f205SBarry Smith   if (flg) {
348fb9695e5SSatish Balay     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_(fd->comm),PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
349b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
350b0a32e0cSBarry Smith     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
351ae09f205SBarry Smith   }
352b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg);CHKERRQ(ierr);
353005c665bSBarry Smith   if (flg) {
354b0a32e0cSBarry Smith     ierr = MatFDColoringView(fd,PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
355b0a32e0cSBarry Smith     ierr = PetscViewerFlush(PETSC_VIEWER_DRAW_(fd->comm));CHKERRQ(ierr);
356005c665bSBarry Smith   }
3573a40ed3dSBarry Smith   PetscFunctionReturn(0);
358bbf0e169SBarry Smith }
359bbf0e169SBarry Smith 
3604a2ae208SSatish Balay #undef __FUNCT__
3614a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringCreate"
362bbf0e169SBarry Smith /*@C
363639f9d9dSBarry Smith    MatFDColoringCreate - Creates a matrix coloring context for finite difference
364639f9d9dSBarry Smith    computation of Jacobians.
365bbf0e169SBarry Smith 
366ef5ee4d1SLois Curfman McInnes    Collective on Mat
367ef5ee4d1SLois Curfman McInnes 
368639f9d9dSBarry Smith    Input Parameters:
369ef5ee4d1SLois Curfman McInnes +  mat - the matrix containing the nonzero structure of the Jacobian
370ef5ee4d1SLois Curfman McInnes -  iscoloring - the coloring of the matrix
371bbf0e169SBarry Smith 
372bbf0e169SBarry Smith     Output Parameter:
373639f9d9dSBarry Smith .   color - the new coloring context
374bbf0e169SBarry Smith 
37515091d37SBarry Smith     Level: intermediate
37615091d37SBarry Smith 
3776831982aSBarry Smith .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
378d1c39f55SBarry Smith           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
379d1c39f55SBarry Smith           MatFDColoringSetFrequency(), MatFDColoringSetRecompute(), MatFDColoringView(),
380d1c39f55SBarry Smith           MatFDColoringSetParameters()
381bbf0e169SBarry Smith @*/
382dfbe8321SBarry Smith PetscErrorCode MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
383bbf0e169SBarry Smith {
384639f9d9dSBarry Smith   MatFDColoring  c;
385639f9d9dSBarry Smith   MPI_Comm       comm;
386dfbe8321SBarry Smith   PetscErrorCode ierr;
38738baddfdSBarry Smith   PetscInt       M,N;
388639f9d9dSBarry Smith 
3893a40ed3dSBarry Smith   PetscFunctionBegin;
390d5ba7fb7SMatthew Knepley   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
391639f9d9dSBarry Smith   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
39229bbc08cSBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,"Only for square matrices");
393639f9d9dSBarry Smith 
394f881d145SBarry Smith   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
395*52e6d16bSBarry Smith   ierr = PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr);
396639f9d9dSBarry Smith 
397f830108cSBarry Smith   if (mat->ops->fdcoloringcreate) {
398f830108cSBarry Smith     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
399639f9d9dSBarry Smith   } else {
40029bbc08cSBarry Smith     SETERRQ(PETSC_ERR_SUP,"Code not yet written for this matrix type");
401639f9d9dSBarry Smith   }
402639f9d9dSBarry Smith 
40377d8c4bbSBarry Smith   c->error_rel         = PETSC_SQRT_MACHINE_EPSILON;
40477d8c4bbSBarry Smith   c->umin              = 100.0*PETSC_SQRT_MACHINE_EPSILON;
405005c665bSBarry Smith   c->freq              = 1;
40640964ad5SBarry Smith   c->usersetsrecompute = PETSC_FALSE;
40740964ad5SBarry Smith   c->recompute         = PETSC_FALSE;
40849b058dcSBarry Smith   c->currentcolor      = -1;
409639f9d9dSBarry Smith 
410639f9d9dSBarry Smith   *color = c;
411d5ba7fb7SMatthew Knepley   ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
4123a40ed3dSBarry Smith   PetscFunctionReturn(0);
413bbf0e169SBarry Smith }
414bbf0e169SBarry Smith 
4154a2ae208SSatish Balay #undef __FUNCT__
4164a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringDestroy"
417bbf0e169SBarry Smith /*@C
418639f9d9dSBarry Smith     MatFDColoringDestroy - Destroys a matrix coloring context that was created
419639f9d9dSBarry Smith     via MatFDColoringCreate().
420bbf0e169SBarry Smith 
421ef5ee4d1SLois Curfman McInnes     Collective on MatFDColoring
422ef5ee4d1SLois Curfman McInnes 
423b4fc646aSLois Curfman McInnes     Input Parameter:
424639f9d9dSBarry Smith .   c - coloring context
425bbf0e169SBarry Smith 
42615091d37SBarry Smith     Level: intermediate
42715091d37SBarry Smith 
428639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
429bbf0e169SBarry Smith @*/
430dfbe8321SBarry Smith PetscErrorCode MatFDColoringDestroy(MatFDColoring c)
431bbf0e169SBarry Smith {
4326849ba73SBarry Smith   PetscErrorCode ierr;
43338baddfdSBarry Smith   PetscInt       i;
434bbf0e169SBarry Smith 
4353a40ed3dSBarry Smith   PetscFunctionBegin;
4363a40ed3dSBarry Smith   if (--c->refct > 0) PetscFunctionReturn(0);
437d4bb536fSBarry Smith 
438639f9d9dSBarry Smith   for (i=0; i<c->ncolors; i++) {
439606d414cSSatish Balay     if (c->columns[i])         {ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);}
440606d414cSSatish Balay     if (c->rows[i])            {ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);}
441606d414cSSatish Balay     if (c->columnsforrow[i])   {ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);}
44230b34957SBarry Smith     if (c->vscaleforrow && c->vscaleforrow[i]) {ierr = PetscFree(c->vscaleforrow[i]);CHKERRQ(ierr);}
443bbf0e169SBarry Smith   }
444606d414cSSatish Balay   ierr = PetscFree(c->ncolumns);CHKERRQ(ierr);
445606d414cSSatish Balay   ierr = PetscFree(c->columns);CHKERRQ(ierr);
446606d414cSSatish Balay   ierr = PetscFree(c->nrows);CHKERRQ(ierr);
447606d414cSSatish Balay   ierr = PetscFree(c->rows);CHKERRQ(ierr);
448606d414cSSatish Balay   ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr);
44930b34957SBarry Smith   if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);}
4504f113abfSBarry Smith   if (c->vscale)       {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);}
451005c665bSBarry Smith   if (c->w1) {
452005c665bSBarry Smith     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
453005c665bSBarry Smith     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
454005c665bSBarry Smith     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
455005c665bSBarry Smith   }
456d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
4573a40ed3dSBarry Smith   PetscFunctionReturn(0);
458bbf0e169SBarry Smith }
45943a90d84SBarry Smith 
4604a2ae208SSatish Balay #undef __FUNCT__
46149b058dcSBarry Smith #define __FUNCT__ "MatFDColoringGetPerturbedColumns"
46249b058dcSBarry Smith /*@C
46349b058dcSBarry Smith     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
46449b058dcSBarry Smith       that are currently being perturbed.
46549b058dcSBarry Smith 
46649b058dcSBarry Smith     Not Collective
46749b058dcSBarry Smith 
46849b058dcSBarry Smith     Input Parameters:
46949b058dcSBarry Smith .   coloring - coloring context created with MatFDColoringCreate()
47049b058dcSBarry Smith 
47149b058dcSBarry Smith     Output Parameters:
47249b058dcSBarry Smith +   n - the number of local columns being perturbed
47349b058dcSBarry Smith -   cols - the column indices, in global numbering
47449b058dcSBarry Smith 
47549b058dcSBarry Smith    Level: intermediate
47649b058dcSBarry Smith 
47749b058dcSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()
47849b058dcSBarry Smith 
47949b058dcSBarry Smith .keywords: coloring, Jacobian, finite differences
48049b058dcSBarry Smith @*/
48138baddfdSBarry Smith EXTERN PetscErrorCode MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,PetscInt *cols[])
48249b058dcSBarry Smith {
48349b058dcSBarry Smith   PetscFunctionBegin;
48449b058dcSBarry Smith   if (coloring->currentcolor >= 0) {
48549b058dcSBarry Smith     *n    = coloring->ncolumns[coloring->currentcolor];
48649b058dcSBarry Smith     *cols = coloring->columns[coloring->currentcolor];
48749b058dcSBarry Smith   } else {
48849b058dcSBarry Smith     *n = 0;
48949b058dcSBarry Smith   }
49049b058dcSBarry Smith   PetscFunctionReturn(0);
49149b058dcSBarry Smith }
49249b058dcSBarry Smith 
49349b058dcSBarry Smith #undef __FUNCT__
4944a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApply"
49543a90d84SBarry Smith /*@
496e0907662SLois Curfman McInnes     MatFDColoringApply - Given a matrix for which a MatFDColoring context
497e0907662SLois Curfman McInnes     has been created, computes the Jacobian for a function via finite differences.
49843a90d84SBarry Smith 
499fee21e36SBarry Smith     Collective on MatFDColoring
500fee21e36SBarry Smith 
501ef5ee4d1SLois Curfman McInnes     Input Parameters:
502ef5ee4d1SLois Curfman McInnes +   mat - location to store Jacobian
503ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
504ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
505ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
506ef5ee4d1SLois Curfman McInnes 
5078bba8e72SBarry Smith     Options Database Keys:
508b9722508SLois Curfman McInnes +    -mat_fd_coloring_freq <freq> - Sets coloring frequency
509b9722508SLois Curfman McInnes .    -mat_fd_coloring_view - Activates basic viewing or coloring
510b9722508SLois Curfman McInnes .    -mat_fd_coloring_view_draw - Activates drawing of coloring
511b9722508SLois Curfman McInnes -    -mat_fd_coloring_view_info - Activates viewing of coloring info
5128bba8e72SBarry Smith 
51315091d37SBarry Smith     Level: intermediate
51415091d37SBarry Smith 
51543a90d84SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
51643a90d84SBarry Smith 
51743a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences
51843a90d84SBarry Smith @*/
519dfbe8321SBarry Smith PetscErrorCode MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
52043a90d84SBarry Smith {
5216849ba73SBarry Smith   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
5226849ba73SBarry Smith   PetscErrorCode ierr;
52338baddfdSBarry Smith   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
524ea709b57SSatish Balay   PetscScalar    dx,mone = -1.0,*y,*xx,*w3_array;
525ea709b57SSatish Balay   PetscScalar    *vscale_array;
526329f5518SBarry Smith   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
527005c665bSBarry Smith   Vec            w1,w2,w3;
528005c665bSBarry Smith   void           *fctx = coloring->fctx;
529f1af5d2fSBarry Smith   PetscTruth     flg;
530005c665bSBarry Smith 
531a2e34c3dSBarry Smith 
5323a40ed3dSBarry Smith   PetscFunctionBegin;
5334482741eSBarry Smith   PetscValidHeaderSpecific(J,MAT_COOKIE,1);
5344482741eSBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE,2);
5354482741eSBarry Smith   PetscValidHeaderSpecific(x1,VEC_COOKIE,3);
536e0907662SLois Curfman McInnes 
53740964ad5SBarry Smith   if (coloring->usersetsrecompute) {
53840964ad5SBarry Smith     if (!coloring->recompute) {
53940964ad5SBarry Smith       *flag = SAME_PRECONDITIONER;
54076d8deaeSBarry Smith       PetscLogInfo(J,"MatFDColoringApply:Skipping Jacobian, since user called MatFDColorSetRecompute()\n");
54140964ad5SBarry Smith       PetscFunctionReturn(0);
54240964ad5SBarry Smith     } else {
54340964ad5SBarry Smith       coloring->recompute = PETSC_FALSE;
54440964ad5SBarry Smith     }
54540964ad5SBarry Smith   }
54640964ad5SBarry Smith 
547d5ba7fb7SMatthew Knepley   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
54876d8deaeSBarry Smith   if (J->ops->fdcoloringapply) {
54976d8deaeSBarry Smith     ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr);
55076d8deaeSBarry Smith   } else {
55176d8deaeSBarry Smith 
552005c665bSBarry Smith     if (!coloring->w1) {
553005c665bSBarry Smith       ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
554*52e6d16bSBarry Smith       ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr);
555005c665bSBarry Smith       ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
556*52e6d16bSBarry Smith       ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr);
557005c665bSBarry Smith       ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
558*52e6d16bSBarry Smith       ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
559005c665bSBarry Smith     }
560005c665bSBarry Smith     w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
56143a90d84SBarry Smith 
5624c49b128SBarry Smith     ierr = MatSetUnfactored(J);CHKERRQ(ierr);
563b0a32e0cSBarry Smith     ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
564f1af5d2fSBarry Smith     if (flg) {
565b0a32e0cSBarry Smith       PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
566e0907662SLois Curfman McInnes     } else {
5670b9b6f31SBarry Smith       PetscTruth assembled;
5680b9b6f31SBarry Smith       ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
5690b9b6f31SBarry Smith       if (assembled) {
57043a90d84SBarry Smith 	ierr = MatZeroEntries(J);CHKERRQ(ierr);
571e0907662SLois Curfman McInnes       }
5720b9b6f31SBarry Smith     }
57343a90d84SBarry Smith 
57443a90d84SBarry Smith     ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
57543a90d84SBarry Smith     ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
576be2fbe1fSBarry Smith 
5773a7fca6bSBarry Smith     /*
5783a7fca6bSBarry Smith       This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
5793a7fca6bSBarry Smith       coloring->F for the coarser grids from the finest
5803a7fca6bSBarry Smith     */
5813a7fca6bSBarry Smith     if (coloring->F) {
5823a7fca6bSBarry Smith       ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
5833a7fca6bSBarry Smith       ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
5843a7fca6bSBarry Smith       if (m1 != m2) {
5853a7fca6bSBarry Smith 	coloring->F = 0;
5863a7fca6bSBarry Smith       }
5873a7fca6bSBarry Smith     }
5883a7fca6bSBarry Smith 
589be2fbe1fSBarry Smith     if (coloring->F) {
590be2fbe1fSBarry Smith       w1          = coloring->F; /* use already computed value of function */
591be2fbe1fSBarry Smith       coloring->F = 0;
592be2fbe1fSBarry Smith     } else {
59366f9b7ceSBarry Smith       ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
59443a90d84SBarry Smith       ierr = (*f)(sctx,x1,w1,fctx);CHKERRQ(ierr);
59566f9b7ceSBarry Smith       ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
596be2fbe1fSBarry Smith     }
59743a90d84SBarry Smith 
59843a90d84SBarry Smith     /*
5999782cf98SBarry Smith        Compute all the scale factors and share with other processors
6009782cf98SBarry Smith     */
6019782cf98SBarry Smith     ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
6024f113abfSBarry Smith     ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
6039782cf98SBarry Smith     for (k=0; k<coloring->ncolors; k++) {
6049782cf98SBarry Smith       /*
6059782cf98SBarry Smith 	Loop over each column associated with color adding the
6069782cf98SBarry Smith 	perturbation to the vector w3.
6079782cf98SBarry Smith       */
6089782cf98SBarry Smith       for (l=0; l<coloring->ncolumns[k]; l++) {
6099782cf98SBarry Smith 	col = coloring->columns[k][l];    /* column of the matrix we are probing for */
6109782cf98SBarry Smith 	dx  = xx[col];
6115b8514ebSBarry Smith 	if (dx == 0.0) dx = 1.0;
6129782cf98SBarry Smith #if !defined(PETSC_USE_COMPLEX)
6139782cf98SBarry Smith 	if (dx < umin && dx >= 0.0)      dx = umin;
6149782cf98SBarry Smith 	else if (dx < 0.0 && dx > -umin) dx = -umin;
6159782cf98SBarry Smith #else
6169782cf98SBarry Smith 	if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
6179782cf98SBarry Smith 	else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
6189782cf98SBarry Smith #endif
6199782cf98SBarry Smith 	dx                *= epsilon;
62030b34957SBarry Smith 	vscale_array[col] = 1.0/dx;
6219782cf98SBarry Smith       }
6229782cf98SBarry Smith     }
623a2e34c3dSBarry Smith     vscale_array = vscale_array + start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
62430b34957SBarry Smith     ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
62530b34957SBarry Smith     ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
6269782cf98SBarry Smith 
627ce1411ecSBarry Smith     /*  ierr = VecView(coloring->vscale,PETSC_VIEWER_STDOUT_WORLD);
628ce1411ecSBarry Smith 	ierr = VecView(x1,PETSC_VIEWER_STDOUT_WORLD);*/
629b0a32e0cSBarry Smith 
63030b34957SBarry Smith     if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
63130b34957SBarry Smith     else                        vscaleforrow = coloring->columnsforrow;
63230b34957SBarry Smith 
63330b34957SBarry Smith     ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
6349782cf98SBarry Smith     /*
63543a90d84SBarry Smith       Loop over each color
63643a90d84SBarry Smith     */
63743a90d84SBarry Smith     for (k=0; k<coloring->ncolors; k++) {
63849b058dcSBarry Smith       coloring->currentcolor = k;
63943a90d84SBarry Smith       ierr = VecCopy(x1,w3);CHKERRQ(ierr);
64042460c72SBarry Smith       ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
64143a90d84SBarry Smith       /*
64243a90d84SBarry Smith 	Loop over each column associated with color adding the
64343a90d84SBarry Smith 	perturbation to the vector w3.
64443a90d84SBarry Smith       */
64543a90d84SBarry Smith       for (l=0; l<coloring->ncolumns[k]; l++) {
64643a90d84SBarry Smith 	col = coloring->columns[k][l];    /* column of the matrix we are probing for */
64742460c72SBarry Smith 	dx  = xx[col];
6485b8514ebSBarry Smith 	if (dx == 0.0) dx = 1.0;
649aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
650ae09f205SBarry Smith 	if (dx < umin && dx >= 0.0)      dx = umin;
651ae09f205SBarry Smith 	else if (dx < 0.0 && dx > -umin) dx = -umin;
65243a90d84SBarry Smith #else
653329f5518SBarry Smith 	if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
654329f5518SBarry Smith 	else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
65543a90d84SBarry Smith #endif
65643a90d84SBarry Smith 	dx            *= epsilon;
6571302d50aSBarry Smith 	if (!PetscAbsScalar(dx)) SETERRQ(PETSC_ERR_PLIB,"Computed 0 differencing parameter");
65842460c72SBarry Smith 	w3_array[col] += dx;
65943a90d84SBarry Smith       }
66042460c72SBarry Smith       w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
6613b28642cSBarry Smith 
66243a90d84SBarry Smith       /*
663e0907662SLois Curfman McInnes 	Evaluate function at x1 + dx (here dx is a vector of perturbations)
66443a90d84SBarry Smith       */
665a2e34c3dSBarry Smith 
66666f9b7ceSBarry Smith       ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
66743a90d84SBarry Smith       ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
66866f9b7ceSBarry Smith       ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
66943a90d84SBarry Smith       ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
6709782cf98SBarry Smith 
67143a90d84SBarry Smith       /*
672e0907662SLois Curfman McInnes 	Loop over rows of vector, putting results into Jacobian matrix
67343a90d84SBarry Smith       */
6743b28642cSBarry Smith       ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
67543a90d84SBarry Smith       for (l=0; l<coloring->nrows[k]; l++) {
67643a90d84SBarry Smith 	row    = coloring->rows[k][l];
67743a90d84SBarry Smith 	col    = coloring->columnsforrow[k][l];
6785904e1b1SBarry Smith 	y[row] *= vscale_array[vscaleforrow[k][l]];
67943a90d84SBarry Smith 	srow   = row + start;
68043a90d84SBarry Smith 	ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
68143a90d84SBarry Smith       }
6823b28642cSBarry Smith       ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
68343a90d84SBarry Smith     }
68449b058dcSBarry Smith     coloring->currentcolor = -1;
68530b34957SBarry Smith     ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
68642460c72SBarry Smith     xx = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
68743a90d84SBarry Smith     ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68843a90d84SBarry Smith     ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
68976d8deaeSBarry Smith   }
690d5ba7fb7SMatthew Knepley   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
691a2e34c3dSBarry Smith 
692b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_null_space_test",&flg);CHKERRQ(ierr);
693a2e34c3dSBarry Smith   if (flg) {
694a2e34c3dSBarry Smith     ierr = MatNullSpaceTest(J->nullsp,J);CHKERRQ(ierr);
695a2e34c3dSBarry Smith   }
696b9722508SLois Curfman McInnes   ierr = MatFDColoringView_Private(coloring);CHKERRQ(ierr);
697b9722508SLois Curfman McInnes 
6983a40ed3dSBarry Smith   PetscFunctionReturn(0);
69943a90d84SBarry Smith }
700840b8ebdSBarry Smith 
7014a2ae208SSatish Balay #undef __FUNCT__
7024a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApplyTS"
703840b8ebdSBarry Smith /*@
704840b8ebdSBarry Smith     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
705840b8ebdSBarry Smith     has been created, computes the Jacobian for a function via finite differences.
706840b8ebdSBarry Smith 
707fee21e36SBarry Smith    Collective on Mat, MatFDColoring, and Vec
708fee21e36SBarry Smith 
709ef5ee4d1SLois Curfman McInnes     Input Parameters:
7103b28642cSBarry Smith +   mat - location to store Jacobian
711ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
712ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
713ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
714ef5ee4d1SLois Curfman McInnes 
715840b8ebdSBarry Smith    Options Database Keys:
716ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
717840b8ebdSBarry Smith 
71815091d37SBarry Smith    Level: intermediate
71915091d37SBarry Smith 
720840b8ebdSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
721840b8ebdSBarry Smith 
722840b8ebdSBarry Smith .keywords: coloring, Jacobian, finite differences
723840b8ebdSBarry Smith @*/
724dfbe8321SBarry Smith PetscErrorCode MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
725840b8ebdSBarry Smith {
7266849ba73SBarry Smith   PetscErrorCode (*f)(void*,PetscReal,Vec,Vec,void*)=(PetscErrorCode (*)(void*,PetscReal,Vec,Vec,void *))coloring->f;
7276849ba73SBarry Smith   PetscErrorCode ierr;
72838baddfdSBarry Smith   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow;
729ea709b57SSatish Balay   PetscScalar    dx,mone = -1.0,*y,*xx,*w3_array;
730ea709b57SSatish Balay   PetscScalar    *vscale_array;
731329f5518SBarry Smith   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
732840b8ebdSBarry Smith   Vec            w1,w2,w3;
733840b8ebdSBarry Smith   void           *fctx = coloring->fctx;
734f1af5d2fSBarry Smith   PetscTruth     flg;
735840b8ebdSBarry Smith 
7363a40ed3dSBarry Smith   PetscFunctionBegin;
7374482741eSBarry Smith   PetscValidHeaderSpecific(J,MAT_COOKIE,1);
7384482741eSBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE,2);
7394482741eSBarry Smith   PetscValidHeaderSpecific(x1,VEC_COOKIE,4);
740840b8ebdSBarry Smith 
741d5ba7fb7SMatthew Knepley   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
742840b8ebdSBarry Smith   if (!coloring->w1) {
743840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w1);CHKERRQ(ierr);
744*52e6d16bSBarry Smith     ierr = PetscLogObjectParent(coloring,coloring->w1);CHKERRQ(ierr);
745840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w2);CHKERRQ(ierr);
746*52e6d16bSBarry Smith     ierr = PetscLogObjectParent(coloring,coloring->w2);CHKERRQ(ierr);
747840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
748*52e6d16bSBarry Smith     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
749840b8ebdSBarry Smith   }
750840b8ebdSBarry Smith   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
751840b8ebdSBarry Smith 
7525904e1b1SBarry Smith   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
753b0a32e0cSBarry Smith   ierr = PetscOptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg);CHKERRQ(ierr);
754f1af5d2fSBarry Smith   if (flg) {
755b0a32e0cSBarry Smith     PetscLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
756840b8ebdSBarry Smith   } else {
7570b9b6f31SBarry Smith     PetscTruth assembled;
7580b9b6f31SBarry Smith     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
7590b9b6f31SBarry Smith     if (assembled) {
760840b8ebdSBarry Smith       ierr = MatZeroEntries(J);CHKERRQ(ierr);
761840b8ebdSBarry Smith     }
7620b9b6f31SBarry Smith   }
763840b8ebdSBarry Smith 
764840b8ebdSBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
765840b8ebdSBarry Smith   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
76666f9b7ceSBarry Smith   ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
767840b8ebdSBarry Smith   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
76866f9b7ceSBarry Smith   ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
769840b8ebdSBarry Smith 
770840b8ebdSBarry Smith   /*
7715904e1b1SBarry Smith       Compute all the scale factors and share with other processors
772840b8ebdSBarry Smith   */
7735904e1b1SBarry Smith   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
7745904e1b1SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
775840b8ebdSBarry Smith   for (k=0; k<coloring->ncolors; k++) {
776840b8ebdSBarry Smith     /*
777840b8ebdSBarry Smith        Loop over each column associated with color adding the
778840b8ebdSBarry Smith        perturbation to the vector w3.
779840b8ebdSBarry Smith     */
780840b8ebdSBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
781840b8ebdSBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
7825904e1b1SBarry Smith       dx  = xx[col];
7835b8514ebSBarry Smith       if (dx == 0.0) dx = 1.0;
784aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
785840b8ebdSBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
786840b8ebdSBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
787840b8ebdSBarry Smith #else
788329f5518SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
789329f5518SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
790840b8ebdSBarry Smith #endif
791840b8ebdSBarry Smith       dx                *= epsilon;
7925904e1b1SBarry Smith       vscale_array[col] = 1.0/dx;
793840b8ebdSBarry Smith     }
7945904e1b1SBarry Smith   }
7955904e1b1SBarry Smith   vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
7965904e1b1SBarry Smith   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7975904e1b1SBarry Smith   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7985904e1b1SBarry Smith 
7995904e1b1SBarry Smith   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
8005904e1b1SBarry Smith   else                        vscaleforrow = coloring->columnsforrow;
8015904e1b1SBarry Smith 
8025904e1b1SBarry Smith   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
8035904e1b1SBarry Smith   /*
8045904e1b1SBarry Smith       Loop over each color
8055904e1b1SBarry Smith   */
8065904e1b1SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
8075904e1b1SBarry Smith     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
8085904e1b1SBarry Smith     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
8095904e1b1SBarry Smith     /*
8105904e1b1SBarry Smith        Loop over each column associated with color adding the
8115904e1b1SBarry Smith        perturbation to the vector w3.
8125904e1b1SBarry Smith     */
8135904e1b1SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
8145904e1b1SBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
8155904e1b1SBarry Smith       dx  = xx[col];
8165b8514ebSBarry Smith       if (dx == 0.0) dx = 1.0;
8175904e1b1SBarry Smith #if !defined(PETSC_USE_COMPLEX)
8185904e1b1SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
8195904e1b1SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
8205904e1b1SBarry Smith #else
8215904e1b1SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
8225904e1b1SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
8235904e1b1SBarry Smith #endif
8245904e1b1SBarry Smith       dx            *= epsilon;
8255904e1b1SBarry Smith       w3_array[col] += dx;
8265904e1b1SBarry Smith     }
8275904e1b1SBarry Smith     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
8285904e1b1SBarry Smith 
829840b8ebdSBarry Smith     /*
830840b8ebdSBarry Smith        Evaluate function at x1 + dx (here dx is a vector of perturbations)
831840b8ebdSBarry Smith     */
83266f9b7ceSBarry Smith     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
833840b8ebdSBarry Smith     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
83466f9b7ceSBarry Smith     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
835840b8ebdSBarry Smith     ierr = VecAXPY(&mone,w1,w2);CHKERRQ(ierr);
8365904e1b1SBarry Smith 
837840b8ebdSBarry Smith     /*
838840b8ebdSBarry Smith        Loop over rows of vector, putting results into Jacobian matrix
839840b8ebdSBarry Smith     */
8403b28642cSBarry Smith     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
841840b8ebdSBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
842840b8ebdSBarry Smith       row    = coloring->rows[k][l];
843840b8ebdSBarry Smith       col    = coloring->columnsforrow[k][l];
8445904e1b1SBarry Smith       y[row] *= vscale_array[vscaleforrow[k][l]];
845840b8ebdSBarry Smith       srow   = row + start;
846840b8ebdSBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
847840b8ebdSBarry Smith     }
8483b28642cSBarry Smith     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
849840b8ebdSBarry Smith   }
8505904e1b1SBarry Smith   ierr  = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
8515904e1b1SBarry Smith   xx    = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
852840b8ebdSBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
853840b8ebdSBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
854d5ba7fb7SMatthew Knepley   ierr  = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
8553a40ed3dSBarry Smith   PetscFunctionReturn(0);
856840b8ebdSBarry Smith }
8573b28642cSBarry Smith 
8583b28642cSBarry Smith 
8594a2ae208SSatish Balay #undef __FUNCT__
8604a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetRecompute()"
86140964ad5SBarry Smith /*@C
86240964ad5SBarry Smith    MatFDColoringSetRecompute - Indicates that the next time a Jacobian preconditioner
86340964ad5SBarry Smith      is needed it sholuld be recomputed. Once this is called and the new Jacobian is computed
86440964ad5SBarry Smith      no additional Jacobian's will be computed (the same one will be used) until this is
86540964ad5SBarry Smith      called again.
86640964ad5SBarry Smith 
86740964ad5SBarry Smith    Collective on MatFDColoring
86840964ad5SBarry Smith 
86940964ad5SBarry Smith    Input  Parameters:
87040964ad5SBarry Smith .  c - the coloring context
87140964ad5SBarry Smith 
87240964ad5SBarry Smith    Level: intermediate
87340964ad5SBarry Smith 
87440964ad5SBarry Smith    Notes: The MatFDColoringSetFrequency() is ignored once this is called
87540964ad5SBarry Smith 
87640964ad5SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringSetFrequency()
87740964ad5SBarry Smith 
87840964ad5SBarry Smith .keywords: Mat, finite differences, coloring
87940964ad5SBarry Smith @*/
880dfbe8321SBarry Smith PetscErrorCode MatFDColoringSetRecompute(MatFDColoring c)
88140964ad5SBarry Smith {
88240964ad5SBarry Smith   PetscFunctionBegin;
8834482741eSBarry Smith   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE,1);
88440964ad5SBarry Smith   c->usersetsrecompute = PETSC_TRUE;
88540964ad5SBarry Smith   c->recompute         = PETSC_TRUE;
88640964ad5SBarry Smith   PetscFunctionReturn(0);
88740964ad5SBarry Smith }
88840964ad5SBarry Smith 
8893b28642cSBarry Smith 
890