xref: /petsc/src/mat/matfd/fdmatrix.c (revision e20fef11c1a1457fc77d0de77d14a2dd6b3370e4)
1840b8ebdSBarry Smith 
2a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
3*e20fef11SSatish Balay static char vcid[] = "$Id: fdmatrix.c,v 1.33 1998/04/27 04:03:35 curfman Exp balay $";
4bbf0e169SBarry Smith #endif
5bbf0e169SBarry Smith 
6bbf0e169SBarry Smith /*
7639f9d9dSBarry Smith    This is where the abstract matrix operations are defined that are
8639f9d9dSBarry Smith   used for finite difference computations of Jacobians using coloring.
9bbf0e169SBarry Smith */
10bbf0e169SBarry Smith 
11bbf0e169SBarry Smith #include "petsc.h"
12bbf0e169SBarry Smith #include "src/mat/matimpl.h"        /*I "mat.h" I*/
13bbf0e169SBarry Smith #include "src/vec/vecimpl.h"
14bbf0e169SBarry Smith #include "pinclude/pviewer.h"
15bbf0e169SBarry Smith 
165615d1e5SSatish Balay #undef __FUNC__
17d4bb536fSBarry Smith #define __FUNC__ "MatFDColoringView_Draw"
18005c665bSBarry Smith static int MatFDColoringView_Draw(MatFDColoring fd,Viewer viewer)
19005c665bSBarry Smith {
20005c665bSBarry Smith   int         ierr,i,j,pause;
21005c665bSBarry Smith   PetscTruth  isnull;
22005c665bSBarry Smith   Draw        draw;
23d4bb536fSBarry Smith   double      xr,yr,xl,yl,h,w,x,y,xc,yc,scale = 0.0;
24005c665bSBarry Smith   DrawButton  button;
25005c665bSBarry Smith 
263a40ed3dSBarry Smith   PetscFunctionBegin;
27005c665bSBarry Smith   ierr = ViewerDrawGetDraw(viewer,&draw); CHKERRQ(ierr);
283a40ed3dSBarry Smith   ierr = DrawIsNull(draw,&isnull); CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
292bdab257SBarry Smith   ierr = DrawSynchronizedClear(draw); CHKERRQ(ierr);
30005c665bSBarry Smith 
31005c665bSBarry Smith   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
32005c665bSBarry Smith   xr += w;    yr += h;  xl = -w;     yl = -h;
33005c665bSBarry Smith   ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
34005c665bSBarry Smith 
35005c665bSBarry Smith   /* loop over colors  */
36005c665bSBarry Smith   for (i=0; i<fd->ncolors; i++ ) {
37005c665bSBarry Smith     for ( j=0; j<fd->nrows[i]; j++ ) {
38005c665bSBarry Smith       y = fd->M - fd->rows[i][j] - fd->rstart;
39005c665bSBarry Smith       x = fd->columnsforrow[i][j];
405cd90555SBarry Smith       ierr = DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1); CHKERRQ(ierr);
41005c665bSBarry Smith     }
42005c665bSBarry Smith   }
432bdab257SBarry Smith   ierr = DrawSynchronizedFlush(draw); CHKERRQ(ierr);
44005c665bSBarry Smith   ierr = DrawGetPause(draw,&pause); CHKERRQ(ierr);
453a40ed3dSBarry Smith   if (pause >= 0) { PetscSleep(pause); PetscFunctionReturn(0);}
465cd90555SBarry Smith   ierr = DrawCheckResizedWindow(draw); CHKERRQ(ierr);
475cd90555SBarry Smith   ierr = DrawSynchronizedGetMouseButton(draw,&button,&xc,&yc,0,0);  CHKERRQ(ierr);
48005c665bSBarry Smith   while (button != BUTTON_RIGHT) {
492bdab257SBarry Smith     ierr = DrawSynchronizedClear(draw); CHKERRQ(ierr);
50005c665bSBarry Smith     if (button == BUTTON_LEFT) scale = .5;
51005c665bSBarry Smith     else if (button == BUTTON_CENTER) scale = 2.;
52005c665bSBarry Smith     xl = scale*(xl + w - xc) + xc - w*scale;
53005c665bSBarry Smith     xr = scale*(xr - w - xc) + xc + w*scale;
54005c665bSBarry Smith     yl = scale*(yl + h - yc) + yc - h*scale;
55005c665bSBarry Smith     yr = scale*(yr - h - yc) + yc + h*scale;
56005c665bSBarry Smith     w *= scale; h *= scale;
57005c665bSBarry Smith     ierr = DrawSetCoordinates(draw,xl,yl,xr,yr); CHKERRQ(ierr);
58005c665bSBarry Smith     /* loop over colors  */
59005c665bSBarry Smith     for (i=0; i<fd->ncolors; i++ ) {
60005c665bSBarry Smith       for ( j=0; j<fd->nrows[i]; j++ ) {
61005c665bSBarry Smith         y = fd->M - fd->rows[i][j] - fd->rstart;
62005c665bSBarry Smith         x = fd->columnsforrow[i][j];
635cd90555SBarry Smith         ierr = DrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1); CHKERRQ(ierr);
64005c665bSBarry Smith       }
65005c665bSBarry Smith     }
665cd90555SBarry Smith     ierr = DrawCheckResizedWindow(draw); CHKERRQ(ierr);
675cd90555SBarry Smith     ierr = DrawSynchronizedGetMouseButton(draw,&button,&xc,&yc,0,0);  CHKERRQ(ierr);
68005c665bSBarry Smith   }
69005c665bSBarry Smith 
703a40ed3dSBarry Smith   PetscFunctionReturn(0);
71005c665bSBarry Smith }
72005c665bSBarry Smith 
73005c665bSBarry Smith #undef __FUNC__
74d4bb536fSBarry Smith #define __FUNC__ "MatFDColoringView"
75bbf0e169SBarry Smith /*@C
76639f9d9dSBarry Smith    MatFDColoringView - Views a finite difference coloring context.
77bbf0e169SBarry Smith 
78fee21e36SBarry Smith    Collective on MatFDColoring unless Viewer is VIEWER_STDOUT_SELF
79fee21e36SBarry Smith 
80ef5ee4d1SLois Curfman McInnes    Input  Parameters:
81ef5ee4d1SLois Curfman McInnes +  c - the coloring context
82ef5ee4d1SLois Curfman McInnes -  viewer - visualization context
83ef5ee4d1SLois Curfman McInnes 
84b4fc646aSLois Curfman McInnes    Notes:
85b4fc646aSLois Curfman McInnes    The available visualization contexts include
86ef5ee4d1SLois Curfman McInnes +     VIEWER_STDOUT_SELF - standard output (default)
87ef5ee4d1SLois Curfman McInnes .     VIEWER_STDOUT_WORLD - synchronized standard
88ef5ee4d1SLois Curfman McInnes         output where only the first processor opens
89ef5ee4d1SLois Curfman McInnes         the file.  All other processors send their
90ef5ee4d1SLois Curfman McInnes         data to the first processor to print.
91ef5ee4d1SLois Curfman McInnes -     VIEWER_DRAWX_WORLD - graphical display of nonzero structure
92bbf0e169SBarry Smith 
93639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
94005c665bSBarry Smith 
95b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, view
96bbf0e169SBarry Smith @*/
97b4fc646aSLois Curfman McInnes int MatFDColoringView(MatFDColoring c,Viewer viewer)
98bbf0e169SBarry Smith {
99005c665bSBarry Smith   ViewerType vtype;
100639f9d9dSBarry Smith   int        i,j,format,ierr;
101b4fc646aSLois Curfman McInnes   FILE       *fd;
102bbf0e169SBarry Smith 
1033a40ed3dSBarry Smith   PetscFunctionBegin;
104b4fc646aSLois Curfman McInnes   PetscValidHeaderSpecific(c,MAT_FDCOLORING_COOKIE);
105b4fc646aSLois Curfman McInnes   if (viewer) {PetscValidHeader(viewer);}
106b4fc646aSLois Curfman McInnes   else {viewer = VIEWER_STDOUT_SELF;}
107bbf0e169SBarry Smith 
108005c665bSBarry Smith   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
109005c665bSBarry Smith   if (vtype == DRAW_VIEWER) {
110b4fc646aSLois Curfman McInnes     ierr = MatFDColoringView_Draw(c,viewer); CHKERRQ(ierr);
1113a40ed3dSBarry Smith     PetscFunctionReturn(0);
1125cd90555SBarry Smith   } else if (vtype  == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
113b4fc646aSLois Curfman McInnes     ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
114b4fc646aSLois Curfman McInnes     PetscFPrintf(c->comm,fd,"MatFDColoring Object:\n");
115b4fc646aSLois Curfman McInnes     PetscFPrintf(c->comm,fd,"  Error tolerance=%g\n",c->error_rel);
116b4fc646aSLois Curfman McInnes     PetscFPrintf(c->comm,fd,"  Umin=%g\n",c->umin);
117b4fc646aSLois Curfman McInnes     PetscFPrintf(c->comm,fd,"  Number of colors=%d\n",c->ncolors);
118ae09f205SBarry Smith 
119ae09f205SBarry Smith     ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr);
120ae09f205SBarry Smith     if (format != VIEWER_FORMAT_ASCII_INFO) {
121b4fc646aSLois Curfman McInnes       for ( i=0; i<c->ncolors; i++ ) {
122b4fc646aSLois Curfman McInnes         PetscFPrintf(c->comm,fd,"  Information for color %d\n",i);
123b4fc646aSLois Curfman McInnes         PetscFPrintf(c->comm,fd,"    Number of columns %d\n",c->ncolumns[i]);
124b4fc646aSLois Curfman McInnes         for ( j=0; j<c->ncolumns[i]; j++ ) {
125b4fc646aSLois Curfman McInnes           PetscFPrintf(c->comm,fd,"      %d\n",c->columns[i][j]);
126639f9d9dSBarry Smith         }
127b4fc646aSLois Curfman McInnes         PetscFPrintf(c->comm,fd,"    Number of rows %d\n",c->nrows[i]);
128b4fc646aSLois Curfman McInnes         for ( j=0; j<c->nrows[i]; j++ ) {
129b4fc646aSLois Curfman McInnes           PetscFPrintf(c->comm,fd,"      %d %d \n",c->rows[i][j],c->columnsforrow[i][j]);
130b4fc646aSLois Curfman McInnes         }
131bbf0e169SBarry Smith       }
132bbf0e169SBarry Smith     }
1335cd90555SBarry Smith   } else {
1345cd90555SBarry Smith     SETERRQ(1,1,"Viewer type not supported for this object");
135bbf0e169SBarry Smith   }
1363a40ed3dSBarry Smith   PetscFunctionReturn(0);
137639f9d9dSBarry Smith }
138639f9d9dSBarry Smith 
1395615d1e5SSatish Balay #undef __FUNC__
1405615d1e5SSatish Balay #define __FUNC__ "MatFDColoringSetParameters"
141639f9d9dSBarry Smith /*@
142b4fc646aSLois Curfman McInnes    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
143b4fc646aSLois Curfman McInnes    a Jacobian matrix using finite differences.
144639f9d9dSBarry Smith 
145ef5ee4d1SLois Curfman McInnes    Collective on MatFDColoring
146ef5ee4d1SLois Curfman McInnes 
147ef5ee4d1SLois Curfman McInnes    The Jacobian is estimated with the differencing approximation
148ef5ee4d1SLois Curfman McInnes .vb
149ef5ee4d1SLois Curfman McInnes        J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where
150ef5ee4d1SLois Curfman McInnes        h = error_rel*u[i]                    if  u[i] > umin
151ef5ee4d1SLois Curfman McInnes          = error_rel*umin                    else
152ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
153ef5ee4d1SLois Curfman McInnes .ve
154639f9d9dSBarry Smith 
155639f9d9dSBarry Smith    Input Parameters:
156ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
157639f9d9dSBarry Smith .  error_rel - relative error
158ef5ee4d1SLois Curfman McInnes -  umin - minimum allowable u-value
159fee21e36SBarry Smith 
160b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, parameters
161b4fc646aSLois Curfman McInnes 
162b4fc646aSLois Curfman McInnes .seealso: MatFDColoringCreate()
163639f9d9dSBarry Smith @*/
164639f9d9dSBarry Smith int MatFDColoringSetParameters(MatFDColoring matfd,double error,double umin)
165639f9d9dSBarry Smith {
1663a40ed3dSBarry Smith   PetscFunctionBegin;
167639f9d9dSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
168639f9d9dSBarry Smith 
169639f9d9dSBarry Smith   if (error != PETSC_DEFAULT) matfd->error_rel = error;
170639f9d9dSBarry Smith   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
1713a40ed3dSBarry Smith   PetscFunctionReturn(0);
172639f9d9dSBarry Smith }
173639f9d9dSBarry Smith 
1745615d1e5SSatish Balay #undef __FUNC__
175005c665bSBarry Smith #define __FUNC__ "MatFDColoringSetFrequency"
176005c665bSBarry Smith /*@
177e0907662SLois Curfman McInnes    MatFDColoringSetFrequency - Sets the frequency for computing new Jacobian
178e0907662SLois Curfman McInnes    matrices.
179005c665bSBarry Smith 
180fee21e36SBarry Smith    Collective on MatFDColoring
181fee21e36SBarry Smith 
182ef5ee4d1SLois Curfman McInnes    Input Parameters:
183ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
184ef5ee4d1SLois Curfman McInnes -  freq - frequency (default is 1)
185ef5ee4d1SLois Curfman McInnes 
186e0907662SLois Curfman McInnes    Notes:
187e0907662SLois Curfman McInnes    Using a modified Newton strategy, where the Jacobian remains fixed for several
188e0907662SLois Curfman McInnes    iterations, can be cost effective in terms of overall nonlinear solution
189e0907662SLois Curfman McInnes    efficiency.  This parameter indicates that a new Jacobian will be computed every
190e0907662SLois Curfman McInnes    <freq> nonlinear iterations.
191e0907662SLois Curfman McInnes 
192e0907662SLois Curfman McInnes    Options Database Keys:
193ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq>  - Sets coloring frequency
194005c665bSBarry Smith 
195b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, frequency
196ef5ee4d1SLois Curfman McInnes 
197ef5ee4d1SLois Curfman McInnes .seealso: MatFDColoringCreate(), MatFDColoringGetFrequency()
198005c665bSBarry Smith @*/
199005c665bSBarry Smith int MatFDColoringSetFrequency(MatFDColoring matfd,int freq)
200005c665bSBarry Smith {
2013a40ed3dSBarry Smith   PetscFunctionBegin;
202005c665bSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
203005c665bSBarry Smith 
204005c665bSBarry Smith   matfd->freq = freq;
2053a40ed3dSBarry Smith   PetscFunctionReturn(0);
206005c665bSBarry Smith }
207005c665bSBarry Smith 
208005c665bSBarry Smith #undef __FUNC__
209ff0cfa39SBarry Smith #define __FUNC__ "MatFDColoringGetFrequency"
210ff0cfa39SBarry Smith /*@
211ff0cfa39SBarry Smith    MatFDColoringGetFrequency - Gets the frequency for computing new Jacobian
212ff0cfa39SBarry Smith    matrices.
213ff0cfa39SBarry Smith 
214ef5ee4d1SLois Curfman McInnes    Not Collective
215ef5ee4d1SLois Curfman McInnes 
216ff0cfa39SBarry Smith    Input Parameters:
217ff0cfa39SBarry Smith .  coloring - the coloring context
218ff0cfa39SBarry Smith 
219ff0cfa39SBarry Smith    Output Parameters:
220ff0cfa39SBarry Smith .  freq - frequency (default is 1)
221ff0cfa39SBarry Smith 
222ff0cfa39SBarry Smith    Notes:
223ff0cfa39SBarry Smith    Using a modified Newton strategy, where the Jacobian remains fixed for several
224ff0cfa39SBarry Smith    iterations, can be cost effective in terms of overall nonlinear solution
225ff0cfa39SBarry Smith    efficiency.  This parameter indicates that a new Jacobian will be computed every
226ff0cfa39SBarry Smith    <freq> nonlinear iterations.
227ff0cfa39SBarry Smith 
228ff0cfa39SBarry Smith    Options Database Keys:
229ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
230ff0cfa39SBarry Smith 
231ff0cfa39SBarry Smith .keywords: Mat, finite differences, coloring, get, frequency
232ef5ee4d1SLois Curfman McInnes 
233ef5ee4d1SLois Curfman McInnes .seealso: MatFDColoringSetFrequency()
234ff0cfa39SBarry Smith @*/
235ff0cfa39SBarry Smith int MatFDColoringGetFrequency(MatFDColoring matfd,int *freq)
236ff0cfa39SBarry Smith {
2373a40ed3dSBarry Smith   PetscFunctionBegin;
238ff0cfa39SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
239ff0cfa39SBarry Smith 
240ff0cfa39SBarry Smith   *freq = matfd->freq;
2413a40ed3dSBarry Smith   PetscFunctionReturn(0);
242ff0cfa39SBarry Smith }
243ff0cfa39SBarry Smith 
244ff0cfa39SBarry Smith #undef __FUNC__
245005c665bSBarry Smith #define __FUNC__ "MatFDColoringSetFunction"
246d64ed03dSBarry Smith /*@C
247005c665bSBarry Smith    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
248005c665bSBarry Smith 
249fee21e36SBarry Smith    Collective on MatFDColoring
250fee21e36SBarry Smith 
251ef5ee4d1SLois Curfman McInnes    Input Parameters:
252ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
253ef5ee4d1SLois Curfman McInnes .  f - the function
254ef5ee4d1SLois Curfman McInnes -  fctx - the optional user-defined function context
255ef5ee4d1SLois Curfman McInnes 
256b4fc646aSLois Curfman McInnes .keywords: Mat, Jacobian, finite differences, set, function
257005c665bSBarry Smith @*/
258840b8ebdSBarry Smith int MatFDColoringSetFunction(MatFDColoring matfd,int (*f)(void),void *fctx)
259005c665bSBarry Smith {
2603a40ed3dSBarry Smith   PetscFunctionBegin;
261005c665bSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
262005c665bSBarry Smith 
263005c665bSBarry Smith   matfd->f    = f;
264005c665bSBarry Smith   matfd->fctx = fctx;
265005c665bSBarry Smith 
2663a40ed3dSBarry Smith   PetscFunctionReturn(0);
267005c665bSBarry Smith }
268005c665bSBarry Smith 
269005c665bSBarry Smith #undef __FUNC__
270d4bb536fSBarry Smith #define __FUNC__ "MatFDColoringSetFromOptions"
271639f9d9dSBarry Smith /*@
272b4fc646aSLois Curfman McInnes    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
273639f9d9dSBarry Smith    the options database.
274639f9d9dSBarry Smith 
275fee21e36SBarry Smith    Collective on MatFDColoring
276fee21e36SBarry Smith 
277ef5ee4d1SLois Curfman McInnes    The Jacobian is estimated with the differencing approximation
278ef5ee4d1SLois Curfman McInnes .vb
279ef5ee4d1SLois Curfman McInnes        J(u)_{:,i} = [J(u+h*dx_{i}) - J(u)]/h where
280ef5ee4d1SLois Curfman McInnes        h = error_rel*u[i]                    if  u[i] > umin
281ef5ee4d1SLois Curfman McInnes          = error_rel*umin                      else
282ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
283ef5ee4d1SLois Curfman McInnes .ve
284ef5ee4d1SLois Curfman McInnes 
285ef5ee4d1SLois Curfman McInnes    Input Parameter:
286ef5ee4d1SLois Curfman McInnes .  coloring - the coloring context
287ef5ee4d1SLois Curfman McInnes 
288b4fc646aSLois Curfman McInnes    Options Database Keys:
289ef5ee4d1SLois Curfman McInnes +  -mat_fd_coloring_error <err> - Sets <err> (square root
290ef5ee4d1SLois Curfman McInnes            of relative error in the function)
291ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_umin <umin> - Sets umin
292ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets frequency of computing a new Jacobian
293ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view - Activates basic viewing
294ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view_info - Activates viewing info
295ef5ee4d1SLois Curfman McInnes -  -mat_fd_coloring_view_draw - Activates drawing
296639f9d9dSBarry Smith 
297b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, parameters
298639f9d9dSBarry Smith @*/
299639f9d9dSBarry Smith int MatFDColoringSetFromOptions(MatFDColoring matfd)
300639f9d9dSBarry Smith {
301005c665bSBarry Smith   int    ierr,flag,freq = 1;
302639f9d9dSBarry Smith   double error = PETSC_DEFAULT,umin = PETSC_DEFAULT;
3033a40ed3dSBarry Smith 
3043a40ed3dSBarry Smith   PetscFunctionBegin;
305639f9d9dSBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_COOKIE);
306639f9d9dSBarry Smith 
307639f9d9dSBarry Smith   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_err",&error,&flag);CHKERRQ(ierr);
308639f9d9dSBarry Smith   ierr = OptionsGetDouble(matfd->prefix,"-mat_fd_coloring_umin",&umin,&flag);CHKERRQ(ierr);
309639f9d9dSBarry Smith   ierr = MatFDColoringSetParameters(matfd,error,umin); CHKERRQ(ierr);
310005c665bSBarry Smith   ierr = OptionsGetInt(matfd->prefix,"-mat_fd_coloring_freq",&freq,&flag);CHKERRQ(ierr);
311005c665bSBarry Smith   ierr = MatFDColoringSetFrequency(matfd,freq);CHKERRQ(ierr);
312005c665bSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-help",&flag); CHKERRQ(ierr);
313639f9d9dSBarry Smith   if (flag) {
314639f9d9dSBarry Smith     ierr = MatFDColoringPrintHelp(matfd); CHKERRQ(ierr);
315639f9d9dSBarry Smith   }
3163a40ed3dSBarry Smith   PetscFunctionReturn(0);
317639f9d9dSBarry Smith }
318639f9d9dSBarry Smith 
3195615d1e5SSatish Balay #undef __FUNC__
320d4bb536fSBarry Smith #define __FUNC__ "MatFDColoringPrintHelp"
321639f9d9dSBarry Smith /*@
322639f9d9dSBarry Smith     MatFDColoringPrintHelp - Prints help message for matrix finite difference calculations
323639f9d9dSBarry Smith     using coloring.
324639f9d9dSBarry Smith 
325ef5ee4d1SLois Curfman McInnes     Collective on MatFDColoring
326ef5ee4d1SLois Curfman McInnes 
327639f9d9dSBarry Smith     Input Parameter:
328639f9d9dSBarry Smith .   fdcoloring - the MatFDColoring context
329639f9d9dSBarry Smith 
330639f9d9dSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringSetFromOptions()
331639f9d9dSBarry Smith @*/
332639f9d9dSBarry Smith int MatFDColoringPrintHelp(MatFDColoring fd)
333639f9d9dSBarry Smith {
3343a40ed3dSBarry Smith   PetscFunctionBegin;
335639f9d9dSBarry Smith   PetscValidHeaderSpecific(fd,MAT_FDCOLORING_COOKIE);
336639f9d9dSBarry Smith 
33776be9ce4SBarry Smith   (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_err <err>: set sqrt rel tol in function, defaults to %g\n",fd->error_rel);
33876be9ce4SBarry Smith   (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_umin <umin>: see users manual, defaults to %d\n",fd->umin);
33976be9ce4SBarry Smith   (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_freq <freq>: frequency that Jacobian is recomputed, defaults to %d\n",fd->freq);
34076be9ce4SBarry Smith   (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view\n");
34176be9ce4SBarry Smith   (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_draw\n");
34276be9ce4SBarry Smith   (*PetscHelpPrintf)(fd->comm,"-mat_fd_coloring_view_info\n");
3433a40ed3dSBarry Smith   PetscFunctionReturn(0);
344005c665bSBarry Smith }
345005c665bSBarry Smith 
346005c665bSBarry Smith int MatFDColoringView_Private(MatFDColoring fd)
347005c665bSBarry Smith {
348005c665bSBarry Smith   int ierr,flg;
349005c665bSBarry Smith 
3503a40ed3dSBarry Smith   PetscFunctionBegin;
351005c665bSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view",&flg); CHKERRQ(ierr);
352005c665bSBarry Smith   if (flg) {
353f8590f6eSBarry Smith     ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm)); CHKERRQ(ierr);
354005c665bSBarry Smith   }
355ae09f205SBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_info",&flg); CHKERRQ(ierr);
356ae09f205SBarry Smith   if (flg) {
357f8590f6eSBarry Smith     ierr = ViewerPushFormat(VIEWER_STDOUT_(fd->comm),VIEWER_FORMAT_ASCII_INFO,PETSC_NULL);CHKERRQ(ierr);
358f8590f6eSBarry Smith     ierr = MatFDColoringView(fd,VIEWER_STDOUT_(fd->comm)); CHKERRQ(ierr);
359f8590f6eSBarry Smith     ierr = ViewerPopFormat(VIEWER_STDOUT_(fd->comm));CHKERRQ(ierr);
360ae09f205SBarry Smith   }
361005c665bSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg); CHKERRQ(ierr);
362005c665bSBarry Smith   if (flg) {
363005c665bSBarry Smith     ierr = MatFDColoringView(fd,VIEWER_DRAWX_(fd->comm)); CHKERRQ(ierr);
364005c665bSBarry Smith     ierr = ViewerFlush(VIEWER_DRAWX_(fd->comm)); CHKERRQ(ierr);
365005c665bSBarry Smith   }
3663a40ed3dSBarry Smith   PetscFunctionReturn(0);
367bbf0e169SBarry Smith }
368bbf0e169SBarry Smith 
3695615d1e5SSatish Balay #undef __FUNC__
3705615d1e5SSatish Balay #define __FUNC__ "MatFDColoringCreate"
371bbf0e169SBarry Smith /*@C
372639f9d9dSBarry Smith    MatFDColoringCreate - Creates a matrix coloring context for finite difference
373639f9d9dSBarry Smith    computation of Jacobians.
374bbf0e169SBarry Smith 
375ef5ee4d1SLois Curfman McInnes    Collective on Mat
376ef5ee4d1SLois Curfman McInnes 
377639f9d9dSBarry Smith    Input Parameters:
378ef5ee4d1SLois Curfman McInnes +  mat - the matrix containing the nonzero structure of the Jacobian
379ef5ee4d1SLois Curfman McInnes -  iscoloring - the coloring of the matrix
380bbf0e169SBarry Smith 
381bbf0e169SBarry Smith     Output Parameter:
382639f9d9dSBarry Smith .   color - the new coloring context
383bbf0e169SBarry Smith 
384b4fc646aSLois Curfman McInnes     Options Database Keys:
385ef5ee4d1SLois Curfman McInnes +    -mat_fd_coloring_view - Activates basic viewing or coloring
386ef5ee4d1SLois Curfman McInnes .    -mat_fd_coloring_view_draw - Activates drawing of coloring
387ef5ee4d1SLois Curfman McInnes -    -mat_fd_coloring_view_info - Activates viewing of coloring info
388639f9d9dSBarry Smith 
389639f9d9dSBarry Smith .seealso: MatFDColoringDestroy()
390bbf0e169SBarry Smith @*/
391639f9d9dSBarry Smith int MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
392bbf0e169SBarry Smith {
393639f9d9dSBarry Smith   MatFDColoring c;
394639f9d9dSBarry Smith   MPI_Comm      comm;
395639f9d9dSBarry Smith   int           ierr,M,N;
396639f9d9dSBarry Smith 
3973a40ed3dSBarry Smith   PetscFunctionBegin;
398639f9d9dSBarry Smith   ierr = MatGetSize(mat,&M,&N); CHKERRQ(ierr);
399e3372554SBarry Smith   if (M != N) SETERRQ(PETSC_ERR_SUP,0,"Only for square matrices");
400639f9d9dSBarry Smith 
401639f9d9dSBarry Smith   PetscObjectGetComm((PetscObject)mat,&comm);
402f830108cSBarry Smith   PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_COOKIE,0,comm,MatFDColoringDestroy,MatFDColoringView);
403639f9d9dSBarry Smith   PLogObjectCreate(c);
404639f9d9dSBarry Smith 
405f830108cSBarry Smith   if (mat->ops->fdcoloringcreate) {
406f830108cSBarry Smith     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c); CHKERRQ(ierr);
407639f9d9dSBarry Smith   } else {
408e3372554SBarry Smith     SETERRQ(PETSC_ERR_SUP,0,"Code not yet written for this matrix type");
409639f9d9dSBarry Smith   }
410639f9d9dSBarry Smith 
411639f9d9dSBarry Smith   c->error_rel = 1.e-8;
412ae09f205SBarry Smith   c->umin      = 1.e-6;
413005c665bSBarry Smith   c->freq      = 1;
414005c665bSBarry Smith 
415005c665bSBarry Smith   ierr = MatFDColoringView_Private(c); CHKERRQ(ierr);
416639f9d9dSBarry Smith 
417639f9d9dSBarry Smith   *color = c;
418639f9d9dSBarry Smith 
4193a40ed3dSBarry Smith   PetscFunctionReturn(0);
420bbf0e169SBarry Smith }
421bbf0e169SBarry Smith 
4225615d1e5SSatish Balay #undef __FUNC__
423d4bb536fSBarry Smith #define __FUNC__ "MatFDColoringDestroy"
424bbf0e169SBarry Smith /*@C
425639f9d9dSBarry Smith     MatFDColoringDestroy - Destroys a matrix coloring context that was created
426639f9d9dSBarry Smith     via MatFDColoringCreate().
427bbf0e169SBarry Smith 
428ef5ee4d1SLois Curfman McInnes     Collective on MatFDColoring
429ef5ee4d1SLois Curfman McInnes 
430b4fc646aSLois Curfman McInnes     Input Parameter:
431639f9d9dSBarry Smith .   c - coloring context
432bbf0e169SBarry Smith 
433639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
434bbf0e169SBarry Smith @*/
435639f9d9dSBarry Smith int MatFDColoringDestroy(MatFDColoring c)
436bbf0e169SBarry Smith {
437263760aaSBarry Smith   int i,ierr;
438bbf0e169SBarry Smith 
4393a40ed3dSBarry Smith   PetscFunctionBegin;
4403a40ed3dSBarry Smith   if (--c->refct > 0) PetscFunctionReturn(0);
441d4bb536fSBarry Smith 
442639f9d9dSBarry Smith 
443639f9d9dSBarry Smith   for ( i=0; i<c->ncolors; i++ ) {
444639f9d9dSBarry Smith     if (c->columns[i])       PetscFree(c->columns[i]);
445639f9d9dSBarry Smith     if (c->rows[i])          PetscFree(c->rows[i]);
446639f9d9dSBarry Smith     if (c->columnsforrow[i]) PetscFree(c->columnsforrow[i]);
447bbf0e169SBarry Smith   }
448639f9d9dSBarry Smith   PetscFree(c->ncolumns);
449639f9d9dSBarry Smith   PetscFree(c->columns);
450639f9d9dSBarry Smith   PetscFree(c->nrows);
451639f9d9dSBarry Smith   PetscFree(c->rows);
452639f9d9dSBarry Smith   PetscFree(c->columnsforrow);
453639f9d9dSBarry Smith   PetscFree(c->scale);
454005c665bSBarry Smith   if (c->w1) {
455005c665bSBarry Smith     ierr = VecDestroy(c->w1); CHKERRQ(ierr);
456005c665bSBarry Smith     ierr = VecDestroy(c->w2); CHKERRQ(ierr);
457005c665bSBarry Smith     ierr = VecDestroy(c->w3); CHKERRQ(ierr);
458005c665bSBarry Smith   }
459639f9d9dSBarry Smith   PLogObjectDestroy(c);
460639f9d9dSBarry Smith   PetscHeaderDestroy(c);
4613a40ed3dSBarry Smith   PetscFunctionReturn(0);
462bbf0e169SBarry Smith }
46343a90d84SBarry Smith 
464005c665bSBarry Smith #include "snes.h"
465005c665bSBarry Smith 
4665615d1e5SSatish Balay #undef __FUNC__
4675615d1e5SSatish Balay #define __FUNC__ "MatFDColoringApply"
46843a90d84SBarry Smith /*@
469e0907662SLois Curfman McInnes     MatFDColoringApply - Given a matrix for which a MatFDColoring context
470e0907662SLois Curfman McInnes     has been created, computes the Jacobian for a function via finite differences.
47143a90d84SBarry Smith 
472fee21e36SBarry Smith     Collective on MatFDColoring
473fee21e36SBarry Smith 
474ef5ee4d1SLois Curfman McInnes     Input Parameters:
475ef5ee4d1SLois Curfman McInnes +   mat - location to store Jacobian
476ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
477ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
478ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
479ef5ee4d1SLois Curfman McInnes 
4808bba8e72SBarry Smith    Options Database Keys:
481ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
4828bba8e72SBarry Smith 
48343a90d84SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
48443a90d84SBarry Smith 
48543a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences
48643a90d84SBarry Smith @*/
487005c665bSBarry Smith int MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
48843a90d84SBarry Smith {
489e0907662SLois Curfman McInnes   int           k,fg,ierr,N,start,end,l,row,col,srow;
49043a90d84SBarry Smith   Scalar        dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale;
49143a90d84SBarry Smith   double        epsilon = coloring->error_rel, umin = coloring->umin;
49243a90d84SBarry Smith   MPI_Comm      comm = coloring->comm;
493005c665bSBarry Smith   Vec           w1,w2,w3;
494840b8ebdSBarry Smith   int           (*f)(void *,Vec,Vec,void *) = ( int (*)(void *,Vec,Vec,void *))coloring->f;
495005c665bSBarry Smith   void          *fctx = coloring->fctx;
496005c665bSBarry Smith 
4973a40ed3dSBarry Smith   PetscFunctionBegin;
498e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(J,MAT_COOKIE);
499e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
500e0907662SLois Curfman McInnes   PetscValidHeaderSpecific(x1,VEC_COOKIE);
501e0907662SLois Curfman McInnes 
502005c665bSBarry Smith 
503005c665bSBarry Smith   if (!coloring->w1) {
504005c665bSBarry Smith     ierr = VecDuplicate(x1,&coloring->w1); CHKERRQ(ierr);
505005c665bSBarry Smith     PLogObjectParent(coloring,coloring->w1);
506005c665bSBarry Smith     ierr = VecDuplicate(x1,&coloring->w2); CHKERRQ(ierr);
507005c665bSBarry Smith     PLogObjectParent(coloring,coloring->w2);
508005c665bSBarry Smith     ierr = VecDuplicate(x1,&coloring->w3); CHKERRQ(ierr);
509005c665bSBarry Smith     PLogObjectParent(coloring,coloring->w3);
510005c665bSBarry Smith   }
511005c665bSBarry Smith   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
51243a90d84SBarry Smith 
513e0907662SLois Curfman McInnes   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&fg); CHKERRQ(ierr);
514e0907662SLois Curfman McInnes   if (fg) {
515e0907662SLois Curfman McInnes     PLogInfo(coloring,"MatFDColoringApply: Not calling MatZeroEntries()\n");
516e0907662SLois Curfman McInnes   } else {
51743a90d84SBarry Smith     ierr = MatZeroEntries(J); CHKERRQ(ierr);
518e0907662SLois Curfman McInnes   }
51943a90d84SBarry Smith 
52043a90d84SBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr);
52143a90d84SBarry Smith   ierr = VecGetSize(x1,&N); CHKERRQ(ierr);
52243a90d84SBarry Smith   ierr = VecGetArray(x1,&xx); CHKERRQ(ierr);
52343a90d84SBarry Smith   ierr = (*f)(sctx,x1,w1,fctx); CHKERRQ(ierr);
52443a90d84SBarry Smith 
52543a90d84SBarry Smith   PetscMemzero(wscale,N*sizeof(Scalar));
52643a90d84SBarry Smith   /*
52743a90d84SBarry Smith       Loop over each color
52843a90d84SBarry Smith   */
52943a90d84SBarry Smith 
53043a90d84SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
53143a90d84SBarry Smith     ierr = VecCopy(x1,w3); CHKERRQ(ierr);
53243a90d84SBarry Smith     /*
53343a90d84SBarry Smith        Loop over each column associated with color adding the
53443a90d84SBarry Smith        perturbation to the vector w3.
53543a90d84SBarry Smith     */
53643a90d84SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
53743a90d84SBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
53843a90d84SBarry Smith       dx  = xx[col-start];
539ae09f205SBarry Smith       if (dx == 0.0) dx = 1.0;
5403a40ed3dSBarry Smith #if !defined(USE_PETSC_COMPLEX)
541ae09f205SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
542ae09f205SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
54343a90d84SBarry Smith #else
544*e20fef11SSatish Balay       if (PetscAbsScalar(dx) < umin && PetscReal(dx) >= 0.0)     dx = umin;
545*e20fef11SSatish Balay       else if (PetscReal(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
54643a90d84SBarry Smith #endif
54743a90d84SBarry Smith       dx          *= epsilon;
54843a90d84SBarry Smith       wscale[col] = 1.0/dx;
54943a90d84SBarry Smith       VecSetValues(w3,1,&col,&dx,ADD_VALUES);
55043a90d84SBarry Smith     }
55143a90d84SBarry Smith     VecRestoreArray(x1,&xx);
55243a90d84SBarry Smith     /*
553e0907662SLois Curfman McInnes        Evaluate function at x1 + dx (here dx is a vector of perturbations)
55443a90d84SBarry Smith     */
55543a90d84SBarry Smith     ierr = (*f)(sctx,w3,w2,fctx); CHKERRQ(ierr);
55643a90d84SBarry Smith     ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr);
55743a90d84SBarry Smith     /* Communicate scale to all processors */
5583a40ed3dSBarry Smith #if !defined(USE_PETSC_COMPLEX)
559ca161407SBarry Smith     ierr = MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr);
56043a90d84SBarry Smith #else
561ca161407SBarry Smith     ierr = MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr);
56243a90d84SBarry Smith #endif
56343a90d84SBarry Smith     /*
564e0907662SLois Curfman McInnes        Loop over rows of vector, putting results into Jacobian matrix
56543a90d84SBarry Smith     */
56643a90d84SBarry Smith     VecGetArray(w2,&y);
56743a90d84SBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
56843a90d84SBarry Smith       row    = coloring->rows[k][l];
56943a90d84SBarry Smith       col    = coloring->columnsforrow[k][l];
57043a90d84SBarry Smith       y[row] *= scale[col];
57143a90d84SBarry Smith       srow   = row + start;
57243a90d84SBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
57343a90d84SBarry Smith     }
57443a90d84SBarry Smith     VecRestoreArray(w2,&y);
57543a90d84SBarry Smith   }
57643a90d84SBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
57743a90d84SBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
5783a40ed3dSBarry Smith   PetscFunctionReturn(0);
57943a90d84SBarry Smith }
580840b8ebdSBarry Smith 
581840b8ebdSBarry Smith #include "ts.h"
582840b8ebdSBarry Smith 
583840b8ebdSBarry Smith #undef __FUNC__
584840b8ebdSBarry Smith #define __FUNC__ "MatFDColoringApplyTS"
585840b8ebdSBarry Smith /*@
586840b8ebdSBarry Smith     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
587840b8ebdSBarry Smith     has been created, computes the Jacobian for a function via finite differences.
588840b8ebdSBarry Smith 
589fee21e36SBarry Smith    Collective on Mat, MatFDColoring, and Vec
590fee21e36SBarry Smith 
591ef5ee4d1SLois Curfman McInnes     Input Parameters:
592ef5ee4d1SLois Curfman McInnes _   mat - location to store Jacobian
593ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
594ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
595ef5ee4d1SLois Curfman McInnes -   sctx - optional context required by function (actually a SNES context)
596ef5ee4d1SLois Curfman McInnes 
597840b8ebdSBarry Smith    Options Database Keys:
598ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_freq <freq> - Sets coloring frequency
599840b8ebdSBarry Smith 
600840b8ebdSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView()
601840b8ebdSBarry Smith 
602840b8ebdSBarry Smith .keywords: coloring, Jacobian, finite differences
603840b8ebdSBarry Smith @*/
604840b8ebdSBarry Smith int MatFDColoringApplyTS(Mat J,MatFDColoring coloring,double t,Vec x1,MatStructure *flag,void *sctx)
605840b8ebdSBarry Smith {
606840b8ebdSBarry Smith   int           k,fg,ierr,N,start,end,l,row,col,srow;
607840b8ebdSBarry Smith   Scalar        dx, mone = -1.0,*y,*scale = coloring->scale,*xx,*wscale = coloring->wscale;
608840b8ebdSBarry Smith   double        epsilon = coloring->error_rel, umin = coloring->umin;
609840b8ebdSBarry Smith   MPI_Comm      comm = coloring->comm;
610840b8ebdSBarry Smith   Vec           w1,w2,w3;
611840b8ebdSBarry Smith   int           (*f)(void *,double,Vec,Vec,void *) = ( int (*)(void *,double,Vec,Vec,void *))coloring->f;
612840b8ebdSBarry Smith   void          *fctx = coloring->fctx;
613840b8ebdSBarry Smith 
6143a40ed3dSBarry Smith   PetscFunctionBegin;
615840b8ebdSBarry Smith   PetscValidHeaderSpecific(J,MAT_COOKIE);
616840b8ebdSBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_COOKIE);
617840b8ebdSBarry Smith   PetscValidHeaderSpecific(x1,VEC_COOKIE);
618840b8ebdSBarry Smith 
619840b8ebdSBarry Smith 
620840b8ebdSBarry Smith   if (!coloring->w1) {
621840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w1); CHKERRQ(ierr);
622840b8ebdSBarry Smith     PLogObjectParent(coloring,coloring->w1);
623840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w2); CHKERRQ(ierr);
624840b8ebdSBarry Smith     PLogObjectParent(coloring,coloring->w2);
625840b8ebdSBarry Smith     ierr = VecDuplicate(x1,&coloring->w3); CHKERRQ(ierr);
626840b8ebdSBarry Smith     PLogObjectParent(coloring,coloring->w3);
627840b8ebdSBarry Smith   }
628840b8ebdSBarry Smith   w1 = coloring->w1; w2 = coloring->w2; w3 = coloring->w3;
629840b8ebdSBarry Smith 
630840b8ebdSBarry Smith   ierr = OptionsHasName(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&fg); CHKERRQ(ierr);
631840b8ebdSBarry Smith   if (fg) {
632840b8ebdSBarry Smith     PLogInfo(coloring,"MatFDColoringApplyTS: Not calling MatZeroEntries()\n");
633840b8ebdSBarry Smith   } else {
634840b8ebdSBarry Smith     ierr = MatZeroEntries(J); CHKERRQ(ierr);
635840b8ebdSBarry Smith   }
636840b8ebdSBarry Smith 
637840b8ebdSBarry Smith   ierr = VecGetOwnershipRange(x1,&start,&end); CHKERRQ(ierr);
638840b8ebdSBarry Smith   ierr = VecGetSize(x1,&N); CHKERRQ(ierr);
639840b8ebdSBarry Smith   ierr = VecGetArray(x1,&xx); CHKERRQ(ierr);
640840b8ebdSBarry Smith   ierr = (*f)(sctx,t,x1,w1,fctx); CHKERRQ(ierr);
641840b8ebdSBarry Smith 
642840b8ebdSBarry Smith   PetscMemzero(wscale,N*sizeof(Scalar));
643840b8ebdSBarry Smith   /*
644840b8ebdSBarry Smith       Loop over each color
645840b8ebdSBarry Smith   */
646840b8ebdSBarry Smith 
647840b8ebdSBarry Smith   for (k=0; k<coloring->ncolors; k++) {
648840b8ebdSBarry Smith     ierr = VecCopy(x1,w3); CHKERRQ(ierr);
649840b8ebdSBarry Smith     /*
650840b8ebdSBarry Smith        Loop over each column associated with color adding the
651840b8ebdSBarry Smith        perturbation to the vector w3.
652840b8ebdSBarry Smith     */
653840b8ebdSBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
654840b8ebdSBarry Smith       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
655840b8ebdSBarry Smith       dx  = xx[col-start];
656840b8ebdSBarry Smith       if (dx == 0.0) dx = 1.0;
6573a40ed3dSBarry Smith #if !defined(USE_PETSC_COMPLEX)
658840b8ebdSBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
659840b8ebdSBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
660840b8ebdSBarry Smith #else
661*e20fef11SSatish Balay       if (PetscAbsScalar(dx) < umin && PetscReal(dx) >= 0.0)     dx = umin;
662*e20fef11SSatish Balay       else if (PetscReal(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
663840b8ebdSBarry Smith #endif
664840b8ebdSBarry Smith       dx          *= epsilon;
665840b8ebdSBarry Smith       wscale[col] = 1.0/dx;
666840b8ebdSBarry Smith       VecSetValues(w3,1,&col,&dx,ADD_VALUES);
667840b8ebdSBarry Smith     }
668840b8ebdSBarry Smith     VecRestoreArray(x1,&xx);
669840b8ebdSBarry Smith     /*
670840b8ebdSBarry Smith        Evaluate function at x1 + dx (here dx is a vector of perturbations)
671840b8ebdSBarry Smith     */
672840b8ebdSBarry Smith     ierr = (*f)(sctx,t,w3,w2,fctx); CHKERRQ(ierr);
673840b8ebdSBarry Smith     ierr = VecAXPY(&mone,w1,w2); CHKERRQ(ierr);
674840b8ebdSBarry Smith     /* Communicate scale to all processors */
6753a40ed3dSBarry Smith #if !defined(USE_PETSC_COMPLEX)
676ca161407SBarry Smith     ierr = MPI_Allreduce(wscale,scale,N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr);
677840b8ebdSBarry Smith #else
678ca161407SBarry Smith     ierr = MPI_Allreduce(wscale,scale,2*N,MPI_DOUBLE,MPI_SUM,comm);CHKERRQ(ierr);
679840b8ebdSBarry Smith #endif
680840b8ebdSBarry Smith     /*
681840b8ebdSBarry Smith        Loop over rows of vector, putting results into Jacobian matrix
682840b8ebdSBarry Smith     */
683840b8ebdSBarry Smith     VecGetArray(w2,&y);
684840b8ebdSBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
685840b8ebdSBarry Smith       row    = coloring->rows[k][l];
686840b8ebdSBarry Smith       col    = coloring->columnsforrow[k][l];
687840b8ebdSBarry Smith       y[row] *= scale[col];
688840b8ebdSBarry Smith       srow   = row + start;
689840b8ebdSBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
690840b8ebdSBarry Smith     }
691840b8ebdSBarry Smith     VecRestoreArray(w2,&y);
692840b8ebdSBarry Smith   }
693840b8ebdSBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
694840b8ebdSBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
6953a40ed3dSBarry Smith   PetscFunctionReturn(0);
696840b8ebdSBarry Smith }
697