xref: /petsc/src/mat/matfd/fdmatrix.c (revision e350db43d4ede48c58cbf6d84bf61b40cece5c9b)
1be1d678aSKris Buschelman 
2bbf0e169SBarry Smith /*
3639f9d9dSBarry Smith    This is where the abstract matrix operations are defined that are
4639f9d9dSBarry Smith   used for finite difference computations of Jacobians using coloring.
5bbf0e169SBarry Smith */
6bbf0e169SBarry Smith 
7b45d2f2cSJed Brown #include <petsc-private/matimpl.h>        /*I "petscmat.h" I*/
8bbf0e169SBarry Smith 
94a2ae208SSatish Balay #undef __FUNCT__
103a7fca6bSBarry Smith #define __FUNCT__ "MatFDColoringSetF"
117087cfbeSBarry Smith PetscErrorCode  MatFDColoringSetF(MatFDColoring fd,Vec F)
123a7fca6bSBarry Smith {
134e269d77SPeter Brune   PetscErrorCode ierr;
143a7fca6bSBarry Smith   PetscFunctionBegin;
154e269d77SPeter Brune   if (F) {
164e269d77SPeter Brune     ierr = VecCopy(F,fd->w1);CHKERRQ(ierr);
174e269d77SPeter Brune     fd->fset = PETSC_TRUE;
184e269d77SPeter Brune   } else {
194e269d77SPeter Brune     fd->fset = PETSC_FALSE;
204e269d77SPeter Brune   }
213a7fca6bSBarry Smith   PetscFunctionReturn(0);
223a7fca6bSBarry Smith }
233a7fca6bSBarry Smith 
243a7fca6bSBarry Smith #undef __FUNCT__
254a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw_Zoom"
266849ba73SBarry Smith static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
279194eea9SBarry Smith {
289194eea9SBarry Smith   MatFDColoring  fd = (MatFDColoring)Aa;
29dfbe8321SBarry Smith   PetscErrorCode ierr;
3038baddfdSBarry Smith   PetscInt       i,j;
319194eea9SBarry Smith   PetscReal      x,y;
329194eea9SBarry Smith 
339194eea9SBarry Smith   PetscFunctionBegin;
349194eea9SBarry Smith 
359194eea9SBarry Smith   /* loop over colors  */
369194eea9SBarry Smith   for (i=0; i<fd->ncolors; i++) {
379194eea9SBarry Smith     for (j=0; j<fd->nrows[i]; j++) {
389194eea9SBarry Smith       y = fd->M - fd->rows[i][j] - fd->rstart;
399194eea9SBarry Smith       x = fd->columnsforrow[i][j];
40b0a32e0cSBarry Smith       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
419194eea9SBarry Smith     }
429194eea9SBarry Smith   }
439194eea9SBarry Smith   PetscFunctionReturn(0);
449194eea9SBarry Smith }
459194eea9SBarry Smith 
464a2ae208SSatish Balay #undef __FUNCT__
474a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView_Draw"
486849ba73SBarry Smith static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
49005c665bSBarry Smith {
50dfbe8321SBarry Smith   PetscErrorCode ierr;
51ace3abfcSBarry Smith   PetscBool      isnull;
52b0a32e0cSBarry Smith   PetscDraw      draw;
5354d96fa3SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
54005c665bSBarry Smith 
553a40ed3dSBarry Smith   PetscFunctionBegin;
56b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
57b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
589194eea9SBarry Smith 
599194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
60005c665bSBarry Smith 
61005c665bSBarry Smith   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
62005c665bSBarry Smith   xr += w;     yr += h;    xl = -w;     yl = -h;
63b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
64b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
659194eea9SBarry Smith   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
663a40ed3dSBarry Smith   PetscFunctionReturn(0);
67005c665bSBarry Smith }
68005c665bSBarry Smith 
694a2ae208SSatish Balay #undef __FUNCT__
704a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringView"
71bbf0e169SBarry Smith /*@C
72639f9d9dSBarry Smith    MatFDColoringView - Views a finite difference coloring context.
73bbf0e169SBarry Smith 
744c49b128SBarry Smith    Collective on MatFDColoring
75fee21e36SBarry Smith 
76ef5ee4d1SLois Curfman McInnes    Input  Parameters:
77ef5ee4d1SLois Curfman McInnes +  c - the coloring context
78ef5ee4d1SLois Curfman McInnes -  viewer - visualization context
79ef5ee4d1SLois Curfman McInnes 
8015091d37SBarry Smith    Level: intermediate
8115091d37SBarry Smith 
82b4fc646aSLois Curfman McInnes    Notes:
83b4fc646aSLois Curfman McInnes    The available visualization contexts include
84b0a32e0cSBarry Smith +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
85b0a32e0cSBarry Smith .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
86ef5ee4d1SLois Curfman McInnes         output where only the first processor opens
87ef5ee4d1SLois Curfman McInnes         the file.  All other processors send their
88ef5ee4d1SLois Curfman McInnes         data to the first processor to print.
89b0a32e0cSBarry Smith -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
90bbf0e169SBarry Smith 
919194eea9SBarry Smith    Notes:
929194eea9SBarry Smith      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
93b0a32e0cSBarry Smith    involves more than 33 then some seemingly identical colors are displayed making it look
949194eea9SBarry Smith    like an illegal coloring. This is just a graphical artifact.
959194eea9SBarry Smith 
96639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
97005c665bSBarry Smith 
98b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, view
99bbf0e169SBarry Smith @*/
1007087cfbeSBarry Smith PetscErrorCode  MatFDColoringView(MatFDColoring c,PetscViewer viewer)
101bbf0e169SBarry Smith {
1026849ba73SBarry Smith   PetscErrorCode    ierr;
10338baddfdSBarry Smith   PetscInt          i,j;
104ace3abfcSBarry Smith   PetscBool         isdraw,iascii;
105f3ef73ceSBarry Smith   PetscViewerFormat format;
106bbf0e169SBarry Smith 
1073a40ed3dSBarry Smith   PetscFunctionBegin;
1080700a824SBarry Smith   PetscValidHeaderSpecific(c,MAT_FDCOLORING_CLASSID,1);
1093050cee2SBarry Smith   if (!viewer) {
1107adad957SLisandro Dalcin     ierr = PetscViewerASCIIGetStdout(((PetscObject)c)->comm,&viewer);CHKERRQ(ierr);
1113050cee2SBarry Smith   }
1120700a824SBarry Smith   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
113c9780b6fSBarry Smith   PetscCheckSameComm(c,1,viewer,2);
114bbf0e169SBarry Smith 
115251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
116251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1170f5bd95cSBarry Smith   if (isdraw) {
118b4fc646aSLois Curfman McInnes     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
11932077d6dSBarry Smith   } else if (iascii) {
120317d6ea6SBarry Smith     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer,"MatFDColoring Object");CHKERRQ(ierr);
121a83599f4SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%G\n",c->error_rel);CHKERRQ(ierr);
122a83599f4SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%G\n",c->umin);CHKERRQ(ierr);
12377431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);CHKERRQ(ierr);
124ae09f205SBarry Smith 
125b0a32e0cSBarry Smith     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
126fb9695e5SSatish Balay     if (format != PETSC_VIEWER_ASCII_INFO) {
127b4fc646aSLois Curfman McInnes       for (i=0; i<c->ncolors; i++) {
12877431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);CHKERRQ(ierr);
12977431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr);
130b4fc646aSLois Curfman McInnes         for (j=0; j<c->ncolumns[i]; j++) {
13177431f27SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);CHKERRQ(ierr);
132639f9d9dSBarry Smith         }
13377431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr);
134b4fc646aSLois Curfman McInnes         for (j=0; j<c->nrows[i]; j++) {
13577431f27SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer,"      %D %D \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
136b4fc646aSLois Curfman McInnes         }
137bbf0e169SBarry Smith       }
138bbf0e169SBarry Smith     }
139b0a32e0cSBarry Smith     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1405cd90555SBarry Smith   } else {
141e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
142bbf0e169SBarry Smith   }
1433a40ed3dSBarry Smith   PetscFunctionReturn(0);
144639f9d9dSBarry Smith }
145639f9d9dSBarry Smith 
1464a2ae208SSatish Balay #undef __FUNCT__
1474a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetParameters"
148639f9d9dSBarry Smith /*@
149b4fc646aSLois Curfman McInnes    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
150b4fc646aSLois Curfman McInnes    a Jacobian matrix using finite differences.
151639f9d9dSBarry Smith 
1523f9fe445SBarry Smith    Logically Collective on MatFDColoring
153ef5ee4d1SLois Curfman McInnes 
154ef5ee4d1SLois Curfman McInnes    The Jacobian is estimated with the differencing approximation
155ef5ee4d1SLois Curfman McInnes .vb
15665f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
157f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
158f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
159ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
160ef5ee4d1SLois Curfman McInnes .ve
161639f9d9dSBarry Smith 
162639f9d9dSBarry Smith    Input Parameters:
163ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
164639f9d9dSBarry Smith .  error_rel - relative error
165f23b5b22SLois Curfman McInnes -  umin - minimum allowable u-value magnitude
166fee21e36SBarry Smith 
16715091d37SBarry Smith    Level: advanced
16815091d37SBarry Smith 
169b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, coloring, set, parameters
170b4fc646aSLois Curfman McInnes 
17195b89fc3SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()
17295b89fc3SBarry Smith 
173639f9d9dSBarry Smith @*/
1747087cfbeSBarry Smith PetscErrorCode  MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
175639f9d9dSBarry Smith {
1763a40ed3dSBarry Smith   PetscFunctionBegin;
1770700a824SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
178c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(matfd,error,2);
179c5eb9154SBarry Smith   PetscValidLogicalCollectiveReal(matfd,umin,3);
180639f9d9dSBarry Smith   if (error != PETSC_DEFAULT) matfd->error_rel = error;
181639f9d9dSBarry Smith   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
1823a40ed3dSBarry Smith   PetscFunctionReturn(0);
183639f9d9dSBarry Smith }
184639f9d9dSBarry Smith 
185005c665bSBarry Smith 
186ff0cfa39SBarry Smith 
1874a2ae208SSatish Balay #undef __FUNCT__
1884a9d489dSBarry Smith #define __FUNCT__ "MatFDColoringGetFunction"
1894a9d489dSBarry Smith /*@C
1904a9d489dSBarry Smith    MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.
1914a9d489dSBarry Smith 
1923f9fe445SBarry Smith    Not Collective
1934a9d489dSBarry Smith 
1944a9d489dSBarry Smith    Input Parameters:
1954a9d489dSBarry Smith .  coloring - the coloring context
1964a9d489dSBarry Smith 
1974a9d489dSBarry Smith    Output Parameters:
1984a9d489dSBarry Smith +  f - the function
1994a9d489dSBarry Smith -  fctx - the optional user-defined function context
2004a9d489dSBarry Smith 
2014a9d489dSBarry Smith    Level: intermediate
2024a9d489dSBarry Smith 
2034a9d489dSBarry Smith .keywords: Mat, Jacobian, finite differences, set, function
20495b89fc3SBarry Smith 
20595b89fc3SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
20695b89fc3SBarry Smith 
2074a9d489dSBarry Smith @*/
2087087cfbeSBarry Smith PetscErrorCode  MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
2094a9d489dSBarry Smith {
2104a9d489dSBarry Smith   PetscFunctionBegin;
2110700a824SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
2124a9d489dSBarry Smith   if (f) *f = matfd->f;
2134a9d489dSBarry Smith   if (fctx) *fctx = matfd->fctx;
2144a9d489dSBarry Smith   PetscFunctionReturn(0);
2154a9d489dSBarry Smith }
2164a9d489dSBarry Smith 
2174a9d489dSBarry Smith #undef __FUNCT__
2184a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFunction"
219d64ed03dSBarry Smith /*@C
220005c665bSBarry Smith    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
221005c665bSBarry Smith 
2223f9fe445SBarry Smith    Logically Collective on MatFDColoring
223fee21e36SBarry Smith 
224ef5ee4d1SLois Curfman McInnes    Input Parameters:
225ef5ee4d1SLois Curfman McInnes +  coloring - the coloring context
226ef5ee4d1SLois Curfman McInnes .  f - the function
227ef5ee4d1SLois Curfman McInnes -  fctx - the optional user-defined function context
228ef5ee4d1SLois Curfman McInnes 
2297850c7c0SBarry Smith    Calling sequence of (*f) function:
2307850c7c0SBarry Smith     For SNES:    PetscErrorCode (*f)(SNES,Vec,Vec,void*)
231ab637aeaSJed Brown     If not using SNES: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored
23215091d37SBarry Smith 
2337850c7c0SBarry Smith    Level: advanced
2347850c7c0SBarry Smith 
235ab637aeaSJed Brown    Notes: This function is usually used automatically by SNES (when one uses SNESSetJacobian() with the argument
236ab637aeaSJed Brown      SNESDefaultComputeJacobianColor()) and only needs to be used by someone computing a matrix via coloring directly by
237ab637aeaSJed Brown      calling MatFDColoringApply()
2387850c7c0SBarry Smith 
2397850c7c0SBarry Smith    Fortran Notes:
2407850c7c0SBarry Smith     In Fortran you must call MatFDColoringSetFunction() for a coloring object to
241ab637aeaSJed Brown   be used without SNES or within the SNES solvers.
242f881d145SBarry Smith 
243b4fc646aSLois Curfman McInnes .keywords: Mat, Jacobian, finite differences, set, function
24495b89fc3SBarry Smith 
24595b89fc3SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringGetFunction(), MatFDColoringSetFromOptions()
24695b89fc3SBarry Smith 
247005c665bSBarry Smith @*/
2487087cfbeSBarry Smith PetscErrorCode  MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
249005c665bSBarry Smith {
2503a40ed3dSBarry Smith   PetscFunctionBegin;
2510700a824SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
252005c665bSBarry Smith   matfd->f    = f;
253005c665bSBarry Smith   matfd->fctx = fctx;
2543a40ed3dSBarry Smith   PetscFunctionReturn(0);
255005c665bSBarry Smith }
256005c665bSBarry Smith 
2574a2ae208SSatish Balay #undef __FUNCT__
2584a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringSetFromOptions"
259639f9d9dSBarry Smith /*@
260b4fc646aSLois Curfman McInnes    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
261639f9d9dSBarry Smith    the options database.
262639f9d9dSBarry Smith 
263fee21e36SBarry Smith    Collective on MatFDColoring
264fee21e36SBarry Smith 
26565f2ba5bSLois Curfman McInnes    The Jacobian, F'(u), is estimated with the differencing approximation
266ef5ee4d1SLois Curfman McInnes .vb
26765f2ba5bSLois Curfman McInnes        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
268f23b5b22SLois Curfman McInnes        h = error_rel*u[i]                 if  abs(u[i]) > umin
269f23b5b22SLois Curfman McInnes          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
270ef5ee4d1SLois Curfman McInnes        dx_{i} = (0, ... 1, .... 0)
271ef5ee4d1SLois Curfman McInnes .ve
272ef5ee4d1SLois Curfman McInnes 
273ef5ee4d1SLois Curfman McInnes    Input Parameter:
274ef5ee4d1SLois Curfman McInnes .  coloring - the coloring context
275ef5ee4d1SLois Curfman McInnes 
276b4fc646aSLois Curfman McInnes    Options Database Keys:
277d15ffeeaSSatish Balay +  -mat_fd_coloring_err <err> - Sets <err> (square root
278ef5ee4d1SLois Curfman McInnes            of relative error in the function)
279f23b5b22SLois Curfman McInnes .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
2803ec795f1SBarry Smith .  -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
281ef5ee4d1SLois Curfman McInnes .  -mat_fd_coloring_view - Activates basic viewing
282*e350db43SBarry Smith .  -mat_fd_coloring_view ::ascii_info - Activates viewing info
283*e350db43SBarry Smith -  -mat_fd_coloring_view draw - Activates drawing
284639f9d9dSBarry Smith 
28515091d37SBarry Smith     Level: intermediate
28615091d37SBarry Smith 
287b4fc646aSLois Curfman McInnes .keywords: Mat, finite differences, parameters
288d1c39f55SBarry Smith 
289d1c39f55SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
290d1c39f55SBarry Smith 
291639f9d9dSBarry Smith @*/
2927087cfbeSBarry Smith PetscErrorCode  MatFDColoringSetFromOptions(MatFDColoring matfd)
293639f9d9dSBarry Smith {
294dfbe8321SBarry Smith   PetscErrorCode ierr;
295ace3abfcSBarry Smith   PetscBool      flg;
296efb30889SBarry Smith   char           value[3];
2973a40ed3dSBarry Smith 
2983a40ed3dSBarry Smith   PetscFunctionBegin;
2990700a824SBarry Smith   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
300639f9d9dSBarry Smith 
3013194b578SJed Brown   ierr = PetscObjectOptionsBegin((PetscObject)matfd);CHKERRQ(ierr);
30287828ca2SBarry Smith     ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
30387828ca2SBarry Smith     ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
3041bc75a8dSBarry Smith     ierr = PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,3,&flg);CHKERRQ(ierr);
305efb30889SBarry Smith     if (flg) {
306efb30889SBarry Smith       if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
307efb30889SBarry Smith       else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
308e32f2f54SBarry Smith       else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
309efb30889SBarry Smith     }
3105d973c19SBarry Smith     /* process any options handlers added with PetscObjectAddOptionsHandler() */
3115d973c19SBarry Smith     ierr = PetscObjectProcessOptionsHandlers((PetscObject)matfd);CHKERRQ(ierr);
312b0a32e0cSBarry Smith   PetscOptionsEnd();CHKERRQ(ierr);
3133a40ed3dSBarry Smith   PetscFunctionReturn(0);
314005c665bSBarry Smith }
315005c665bSBarry Smith 
3164a2ae208SSatish Balay #undef __FUNCT__
317*e350db43SBarry Smith #define __FUNCT__ "MatFDColoringViewFromOptions"
318*e350db43SBarry Smith PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd,const char optionname[])
319005c665bSBarry Smith {
320dfbe8321SBarry Smith   PetscErrorCode ierr;
321*e350db43SBarry Smith   PetscBool      flg;
3223050cee2SBarry Smith   PetscViewer    viewer;
323005c665bSBarry Smith 
3243a40ed3dSBarry Smith   PetscFunctionBegin;
325*e350db43SBarry Smith   ierr = PetscOptionsGetViewer(((PetscObject)fd)->comm,((PetscObject)fd)->prefix,optionname,&viewer,&flg);CHKERRQ(ierr);
326005c665bSBarry Smith   if (flg) {
3273050cee2SBarry Smith     ierr = MatFDColoringView(fd,viewer);CHKERRQ(ierr);
328*e350db43SBarry Smith     ierr = PetscOptionsRestoreViewer(viewer);CHKERRQ(ierr);
329005c665bSBarry Smith   }
3303a40ed3dSBarry Smith   PetscFunctionReturn(0);
331bbf0e169SBarry Smith }
332bbf0e169SBarry Smith 
3334a2ae208SSatish Balay #undef __FUNCT__
3344a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringCreate"
33505869f15SSatish Balay /*@
336639f9d9dSBarry Smith    MatFDColoringCreate - Creates a matrix coloring context for finite difference
337639f9d9dSBarry Smith    computation of Jacobians.
338bbf0e169SBarry Smith 
339ef5ee4d1SLois Curfman McInnes    Collective on Mat
340ef5ee4d1SLois Curfman McInnes 
341639f9d9dSBarry Smith    Input Parameters:
342ef5ee4d1SLois Curfman McInnes +  mat - the matrix containing the nonzero structure of the Jacobian
343e727c939SJed Brown -  iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMCreateColoring()
344bbf0e169SBarry Smith 
345bbf0e169SBarry Smith     Output Parameter:
346639f9d9dSBarry Smith .   color - the new coloring context
347bbf0e169SBarry Smith 
34815091d37SBarry Smith     Level: intermediate
34915091d37SBarry Smith 
3506831982aSBarry Smith .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
351d1c39f55SBarry Smith           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
352e727c939SJed Brown           MatFDColoringView(), MatFDColoringSetParameters(), MatGetColoring(), DMCreateColoring()
353bbf0e169SBarry Smith @*/
3547087cfbeSBarry Smith PetscErrorCode  MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
355bbf0e169SBarry Smith {
356639f9d9dSBarry Smith   MatFDColoring  c;
357639f9d9dSBarry Smith   MPI_Comm       comm;
358dfbe8321SBarry Smith   PetscErrorCode ierr;
35938baddfdSBarry Smith   PetscInt       M,N;
360639f9d9dSBarry Smith 
3613a40ed3dSBarry Smith   PetscFunctionBegin;
362d5ba7fb7SMatthew Knepley   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
363639f9d9dSBarry Smith   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
36417186662SBarry Smith   if (M != N) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Only for square matrices");
365f881d145SBarry Smith   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3663194b578SJed Brown   ierr = PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_CLASSID,0,"MatFDColoring","Jacobian computation via finite differences with coloring","Mat",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr);
367639f9d9dSBarry Smith 
368b8f8c88eSHong Zhang   c->ctype = iscoloring->ctype;
369b8f8c88eSHong Zhang 
370f830108cSBarry Smith   if (mat->ops->fdcoloringcreate) {
371f830108cSBarry Smith     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
372577b14d0SJed Brown   } else SETERRQ1(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Code not yet written for matrix type %s",((PetscObject)mat)->type_name);
373639f9d9dSBarry Smith 
374b8f8c88eSHong Zhang   ierr = MatGetVecs(mat,PETSC_NULL,&c->w1);CHKERRQ(ierr);
375b8f8c88eSHong Zhang   ierr = PetscLogObjectParent(c,c->w1);CHKERRQ(ierr);
376b8f8c88eSHong Zhang   ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr);
377b8f8c88eSHong Zhang   ierr = PetscLogObjectParent(c,c->w2);CHKERRQ(ierr);
378b8f8c88eSHong Zhang 
37977d8c4bbSBarry Smith   c->error_rel         = PETSC_SQRT_MACHINE_EPSILON;
38077d8c4bbSBarry Smith   c->umin              = 100.0*PETSC_SQRT_MACHINE_EPSILON;
38149b058dcSBarry Smith   c->currentcolor      = -1;
382efb30889SBarry Smith   c->htype             = "wp";
3834e269d77SPeter Brune   c->fset              = PETSC_FALSE;
384639f9d9dSBarry Smith 
385639f9d9dSBarry Smith   *color = c;
3864e269d77SPeter Brune   ierr = PetscObjectCompose((PetscObject)mat,"SNESMatFDColoring",(PetscObject)c);CHKERRQ(ierr);
387d5ba7fb7SMatthew Knepley   ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
3883a40ed3dSBarry Smith   PetscFunctionReturn(0);
389bbf0e169SBarry Smith }
390bbf0e169SBarry Smith 
3914a2ae208SSatish Balay #undef __FUNCT__
3924a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringDestroy"
39305869f15SSatish Balay /*@
394639f9d9dSBarry Smith     MatFDColoringDestroy - Destroys a matrix coloring context that was created
395639f9d9dSBarry Smith     via MatFDColoringCreate().
396bbf0e169SBarry Smith 
397ef5ee4d1SLois Curfman McInnes     Collective on MatFDColoring
398ef5ee4d1SLois Curfman McInnes 
399b4fc646aSLois Curfman McInnes     Input Parameter:
400639f9d9dSBarry Smith .   c - coloring context
401bbf0e169SBarry Smith 
40215091d37SBarry Smith     Level: intermediate
40315091d37SBarry Smith 
404639f9d9dSBarry Smith .seealso: MatFDColoringCreate()
405bbf0e169SBarry Smith @*/
4066bf464f9SBarry Smith PetscErrorCode  MatFDColoringDestroy(MatFDColoring *c)
407bbf0e169SBarry Smith {
4086849ba73SBarry Smith   PetscErrorCode ierr;
40938baddfdSBarry Smith   PetscInt       i;
410bbf0e169SBarry Smith 
4113a40ed3dSBarry Smith   PetscFunctionBegin;
4126bf464f9SBarry Smith   if (!*c) PetscFunctionReturn(0);
4136bf464f9SBarry Smith   if (--((PetscObject)(*c))->refct > 0) {*c = 0; PetscFunctionReturn(0);}
414d4bb536fSBarry Smith 
4156bf464f9SBarry Smith   for (i=0; i<(*c)->ncolors; i++) {
4166bf464f9SBarry Smith     ierr = PetscFree((*c)->columns[i]);CHKERRQ(ierr);
4176bf464f9SBarry Smith     ierr = PetscFree((*c)->rows[i]);CHKERRQ(ierr);
4186bf464f9SBarry Smith     ierr = PetscFree((*c)->columnsforrow[i]);CHKERRQ(ierr);
4196bf464f9SBarry Smith     if ((*c)->vscaleforrow) {ierr = PetscFree((*c)->vscaleforrow[i]);CHKERRQ(ierr);}
420bbf0e169SBarry Smith   }
4216bf464f9SBarry Smith   ierr = PetscFree((*c)->ncolumns);CHKERRQ(ierr);
4226bf464f9SBarry Smith   ierr = PetscFree((*c)->columns);CHKERRQ(ierr);
4236bf464f9SBarry Smith   ierr = PetscFree((*c)->nrows);CHKERRQ(ierr);
4246bf464f9SBarry Smith   ierr = PetscFree((*c)->rows);CHKERRQ(ierr);
4256bf464f9SBarry Smith   ierr = PetscFree((*c)->columnsforrow);CHKERRQ(ierr);
4266bf464f9SBarry Smith   ierr = PetscFree((*c)->vscaleforrow);CHKERRQ(ierr);
4276bf464f9SBarry Smith   ierr = VecDestroy(&(*c)->vscale);CHKERRQ(ierr);
4286bf464f9SBarry Smith   ierr = VecDestroy(&(*c)->w1);CHKERRQ(ierr);
4296bf464f9SBarry Smith   ierr = VecDestroy(&(*c)->w2);CHKERRQ(ierr);
4306bf464f9SBarry Smith   ierr = VecDestroy(&(*c)->w3);CHKERRQ(ierr);
431d38fa0fbSBarry Smith   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
4323a40ed3dSBarry Smith   PetscFunctionReturn(0);
433bbf0e169SBarry Smith }
43443a90d84SBarry Smith 
4354a2ae208SSatish Balay #undef __FUNCT__
43649b058dcSBarry Smith #define __FUNCT__ "MatFDColoringGetPerturbedColumns"
43749b058dcSBarry Smith /*@C
43849b058dcSBarry Smith     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
43949b058dcSBarry Smith       that are currently being perturbed.
44049b058dcSBarry Smith 
44149b058dcSBarry Smith     Not Collective
44249b058dcSBarry Smith 
44349b058dcSBarry Smith     Input Parameters:
44449b058dcSBarry Smith .   coloring - coloring context created with MatFDColoringCreate()
44549b058dcSBarry Smith 
44649b058dcSBarry Smith     Output Parameters:
44749b058dcSBarry Smith +   n - the number of local columns being perturbed
44849b058dcSBarry Smith -   cols - the column indices, in global numbering
44949b058dcSBarry Smith 
45049b058dcSBarry Smith    Level: intermediate
45149b058dcSBarry Smith 
45249b058dcSBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()
45349b058dcSBarry Smith 
45449b058dcSBarry Smith .keywords: coloring, Jacobian, finite differences
45549b058dcSBarry Smith @*/
4567087cfbeSBarry Smith PetscErrorCode  MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,PetscInt *cols[])
45749b058dcSBarry Smith {
45849b058dcSBarry Smith   PetscFunctionBegin;
45949b058dcSBarry Smith   if (coloring->currentcolor >= 0) {
46049b058dcSBarry Smith     *n    = coloring->ncolumns[coloring->currentcolor];
46149b058dcSBarry Smith     *cols = coloring->columns[coloring->currentcolor];
46249b058dcSBarry Smith   } else {
46349b058dcSBarry Smith     *n = 0;
46449b058dcSBarry Smith   }
46549b058dcSBarry Smith   PetscFunctionReturn(0);
46649b058dcSBarry Smith }
46749b058dcSBarry Smith 
46849b058dcSBarry Smith #undef __FUNCT__
4694a2ae208SSatish Balay #define __FUNCT__ "MatFDColoringApply"
47043a90d84SBarry Smith /*@
471e0907662SLois Curfman McInnes     MatFDColoringApply - Given a matrix for which a MatFDColoring context
472e0907662SLois Curfman McInnes     has been created, computes the Jacobian for a function via finite differences.
47343a90d84SBarry Smith 
474fee21e36SBarry Smith     Collective on MatFDColoring
475fee21e36SBarry Smith 
476ef5ee4d1SLois Curfman McInnes     Input Parameters:
477ef5ee4d1SLois Curfman McInnes +   mat - location to store Jacobian
478ef5ee4d1SLois Curfman McInnes .   coloring - coloring context created with MatFDColoringCreate()
479ef5ee4d1SLois Curfman McInnes .   x1 - location at which Jacobian is to be computed
4807850c7c0SBarry Smith -   sctx - context required by function, if this is being used with the SNES solver then it is SNES object, otherwise it is null
481ef5ee4d1SLois Curfman McInnes 
4828bba8e72SBarry Smith     Options Database Keys:
483ebd3b9afSBarry Smith +    -mat_fd_type - "wp" or "ds"  (see MATMFFD_WP or MATMFFD_DS)
484b9722508SLois Curfman McInnes .    -mat_fd_coloring_view - Activates basic viewing or coloring
485*e350db43SBarry Smith .    -mat_fd_coloring_view draw - Activates drawing of coloring
486*e350db43SBarry Smith -    -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info
4878bba8e72SBarry Smith 
48815091d37SBarry Smith     Level: intermediate
48998d79826SSatish Balay 
4907850c7c0SBarry Smith .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction()
49143a90d84SBarry Smith 
49243a90d84SBarry Smith .keywords: coloring, Jacobian, finite differences
49343a90d84SBarry Smith @*/
4947087cfbeSBarry Smith PetscErrorCode  MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
49543a90d84SBarry Smith {
4963acb8795SBarry Smith   PetscErrorCode ierr;
4973acb8795SBarry Smith 
4983acb8795SBarry Smith   PetscFunctionBegin;
4990700a824SBarry Smith   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
5000700a824SBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
5010700a824SBarry Smith   PetscValidHeaderSpecific(x1,VEC_CLASSID,3);
50217186662SBarry Smith   if (!coloring->f) SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
503e32f2f54SBarry Smith   if (!J->ops->fdcoloringapply) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)J)->type_name);
5043acb8795SBarry Smith   ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr);
5053acb8795SBarry Smith   PetscFunctionReturn(0);
5063acb8795SBarry Smith }
5073acb8795SBarry Smith 
5083acb8795SBarry Smith #undef __FUNCT__
5093acb8795SBarry Smith #define __FUNCT__ "MatFDColoringApply_AIJ"
5107087cfbeSBarry Smith PetscErrorCode  MatFDColoringApply_AIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
5113acb8795SBarry Smith {
5126849ba73SBarry Smith   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
5136849ba73SBarry Smith   PetscErrorCode ierr;
5144e269d77SPeter Brune   PetscInt       k,start,end,l,row,col,srow,**vscaleforrow;
515efb30889SBarry Smith   PetscScalar    dx,*y,*xx,*w3_array;
516ea709b57SSatish Balay   PetscScalar    *vscale_array;
517efb30889SBarry Smith   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin,unorm;
518b8f8c88eSHong Zhang   Vec            w1=coloring->w1,w2=coloring->w2,w3;
519005c665bSBarry Smith   void           *fctx = coloring->fctx;
520ace3abfcSBarry Smith   PetscBool      flg = PETSC_FALSE;
521705d48f7SSatish Balay   PetscInt       ctype=coloring->ctype,N,col_start=0,col_end=0;
522b8f8c88eSHong Zhang   Vec            x1_tmp;
523a2e34c3dSBarry Smith 
5243a40ed3dSBarry Smith   PetscFunctionBegin;
5250700a824SBarry Smith   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
5260700a824SBarry Smith   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
5270700a824SBarry Smith   PetscValidHeaderSpecific(x1,VEC_CLASSID,3);
52817186662SBarry Smith   if (!f) SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
529e0907662SLois Curfman McInnes 
530d5ba7fb7SMatthew Knepley   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
5314c49b128SBarry Smith   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
532acfcf0e5SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr);
533f1af5d2fSBarry Smith   if (flg) {
534ae15b995SBarry Smith     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
535e0907662SLois Curfman McInnes   } else {
536ace3abfcSBarry Smith     PetscBool  assembled;
5370b9b6f31SBarry Smith     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
5380b9b6f31SBarry Smith     if (assembled) {
53943a90d84SBarry Smith       ierr = MatZeroEntries(J);CHKERRQ(ierr);
540e0907662SLois Curfman McInnes     }
5410b9b6f31SBarry Smith   }
54243a90d84SBarry Smith 
543b8f8c88eSHong Zhang   x1_tmp = x1;
544dac7f5fdSBarry Smith   if (!coloring->vscale){
545b8f8c88eSHong Zhang     ierr = VecDuplicate(x1_tmp,&coloring->vscale);CHKERRQ(ierr);
546b8f8c88eSHong Zhang   }
547be2fbe1fSBarry Smith 
548b8f8c88eSHong Zhang   if (coloring->htype[0] == 'w') { /* tacky test; need to make systematic if we add other approaches to computing h*/
549b8f8c88eSHong Zhang     ierr = VecNorm(x1_tmp,NORM_2,&unorm);CHKERRQ(ierr);
550b8f8c88eSHong Zhang   }
551b8f8c88eSHong Zhang   ierr = VecGetOwnershipRange(w1,&start,&end);CHKERRQ(ierr); /* OwnershipRange is used by ghosted x! */
552b8f8c88eSHong Zhang 
553b8f8c88eSHong Zhang   /* Set w1 = F(x1) */
5544e269d77SPeter Brune   if (!coloring->fset) {
55566f9b7ceSBarry Smith     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
556b8f8c88eSHong Zhang     ierr = (*f)(sctx,x1_tmp,w1,fctx);CHKERRQ(ierr);
55766f9b7ceSBarry Smith     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
5584e269d77SPeter Brune   } else {
5594e269d77SPeter Brune     coloring->fset = PETSC_FALSE;
560be2fbe1fSBarry Smith   }
56143a90d84SBarry Smith 
562b8f8c88eSHong Zhang   if (!coloring->w3) {
563b8f8c88eSHong Zhang     ierr = VecDuplicate(x1_tmp,&coloring->w3);CHKERRQ(ierr);
564b8f8c88eSHong Zhang     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
565efb30889SBarry Smith   }
566b8f8c88eSHong Zhang   w3 = coloring->w3;
567efb30889SBarry Smith 
568b8f8c88eSHong Zhang     /* Compute all the local scale factors, including ghost points */
569b8f8c88eSHong Zhang   ierr = VecGetLocalSize(x1_tmp,&N);CHKERRQ(ierr);
570b8f8c88eSHong Zhang   ierr = VecGetArray(x1_tmp,&xx);CHKERRQ(ierr);
571b8f8c88eSHong Zhang   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
572b8f8c88eSHong Zhang   if (ctype == IS_COLORING_GHOSTED){
573b8f8c88eSHong Zhang     col_start = 0; col_end = N;
5748ee2e534SBarry Smith   } else if (ctype == IS_COLORING_GLOBAL){
575b8f8c88eSHong Zhang     xx = xx - start;
576b8f8c88eSHong Zhang     vscale_array = vscale_array - start;
577b8f8c88eSHong Zhang     col_start = start; col_end = N + start;
578b8f8c88eSHong Zhang   }
579b8f8c88eSHong Zhang   for (col=col_start; col<col_end; col++){
580b8f8c88eSHong Zhang     /* Loop over each local column, vscale[col] = 1./(epsilon*dx[col]) */
581efb30889SBarry Smith     if (coloring->htype[0] == 'w') {
582efb30889SBarry Smith       dx = 1.0 + unorm;
583efb30889SBarry Smith     } else {
5849782cf98SBarry Smith       dx  = xx[col];
585efb30889SBarry Smith     }
586d4a378daSJed Brown     if (dx == (PetscScalar)0.0) dx = 1.0;
5879782cf98SBarry Smith #if !defined(PETSC_USE_COMPLEX)
5889782cf98SBarry Smith     if (dx < umin && dx >= 0.0)      dx = umin;
5899782cf98SBarry Smith     else if (dx < 0.0 && dx > -umin) dx = -umin;
5909782cf98SBarry Smith #else
5919782cf98SBarry Smith     if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
5929782cf98SBarry Smith     else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
5939782cf98SBarry Smith #endif
5949782cf98SBarry Smith     dx               *= epsilon;
595d4a378daSJed Brown     vscale_array[col] = (PetscScalar)1.0/dx;
5969782cf98SBarry Smith   }
5978ee2e534SBarry Smith   if (ctype == IS_COLORING_GLOBAL)  vscale_array = vscale_array + start;
598efb30889SBarry Smith   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
5998ee2e534SBarry Smith   if (ctype == IS_COLORING_GLOBAL){
60030b34957SBarry Smith     ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60130b34957SBarry Smith     ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
602b8f8c88eSHong Zhang   }
6039782cf98SBarry Smith 
604b8f8c88eSHong Zhang   if (coloring->vscaleforrow) {
605b8f8c88eSHong Zhang     vscaleforrow = coloring->vscaleforrow;
60617186662SBarry Smith   } else SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_NULL,"Null Object: coloring->vscaleforrow");
607b0a32e0cSBarry Smith 
6089782cf98SBarry Smith   /*
60943a90d84SBarry Smith     Loop over each color
61043a90d84SBarry Smith   */
611b8f8c88eSHong Zhang   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
61243a90d84SBarry Smith   for (k=0; k<coloring->ncolors; k++) {
61349b058dcSBarry Smith     coloring->currentcolor = k;
614b8f8c88eSHong Zhang     ierr = VecCopy(x1_tmp,w3);CHKERRQ(ierr);
615b8f8c88eSHong Zhang     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);
6168ee2e534SBarry Smith     if (ctype == IS_COLORING_GLOBAL) w3_array = w3_array - start;
61743a90d84SBarry Smith     /*
618b8f8c88eSHong Zhang       Loop over each column associated with color
619b8f8c88eSHong Zhang       adding the perturbation to the vector w3.
62043a90d84SBarry Smith     */
62143a90d84SBarry Smith     for (l=0; l<coloring->ncolumns[k]; l++) {
622b8f8c88eSHong Zhang       col = coloring->columns[k][l];    /* local column of the matrix we are probing for */
623efb30889SBarry Smith       if (coloring->htype[0] == 'w') {
624efb30889SBarry Smith         dx = 1.0 + unorm;
625efb30889SBarry Smith       } else {
62642460c72SBarry Smith         dx  = xx[col];
627efb30889SBarry Smith       }
628d4a378daSJed Brown       if (dx == (PetscScalar)0.0) dx = 1.0;
629aa482453SBarry Smith #if !defined(PETSC_USE_COMPLEX)
630ae09f205SBarry Smith       if (dx < umin && dx >= 0.0)      dx = umin;
631ae09f205SBarry Smith       else if (dx < 0.0 && dx > -umin) dx = -umin;
63243a90d84SBarry Smith #else
633329f5518SBarry Smith       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
634329f5518SBarry Smith       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
63543a90d84SBarry Smith #endif
63643a90d84SBarry Smith       dx            *= epsilon;
637e32f2f54SBarry Smith       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter");
63842460c72SBarry Smith       w3_array[col] += dx;
63943a90d84SBarry Smith     }
64098d79826SSatish Balay     if (ctype == IS_COLORING_GLOBAL) w3_array = w3_array + start;
641b8f8c88eSHong Zhang     ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
6423b28642cSBarry Smith 
64343a90d84SBarry Smith     /*
644b8f8c88eSHong Zhang       Evaluate function at w3 = x1 + dx (here dx is a vector of perturbations)
645b8f8c88eSHong Zhang                            w2 = F(x1 + dx) - F(x1)
64643a90d84SBarry Smith     */
64766f9b7ceSBarry Smith     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
64843a90d84SBarry Smith     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
64966f9b7ceSBarry Smith     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
650efb30889SBarry Smith     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
6519782cf98SBarry Smith 
65243a90d84SBarry Smith     /*
653e0907662SLois Curfman McInnes       Loop over rows of vector, putting results into Jacobian matrix
65443a90d84SBarry Smith     */
6553b28642cSBarry Smith     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
65643a90d84SBarry Smith     for (l=0; l<coloring->nrows[k]; l++) {
657b8f8c88eSHong Zhang       row    = coloring->rows[k][l];             /* local row index */
658b8f8c88eSHong Zhang       col    = coloring->columnsforrow[k][l];    /* global column index */
6595904e1b1SBarry Smith       y[row] *= vscale_array[vscaleforrow[k][l]];
66043a90d84SBarry Smith       srow   = row + start;
66143a90d84SBarry Smith       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
66243a90d84SBarry Smith     }
6633b28642cSBarry Smith     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
664aeb7e98aSMatthew Knepley   } /* endof for each color */
6658ee2e534SBarry Smith   if (ctype == IS_COLORING_GLOBAL) xx = xx + start;
66630b34957SBarry Smith   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
667b8f8c88eSHong Zhang   ierr = VecRestoreArray(x1_tmp,&xx);CHKERRQ(ierr);
668b8f8c88eSHong Zhang 
669b8f8c88eSHong Zhang   coloring->currentcolor = -1;
67043a90d84SBarry Smith   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
67143a90d84SBarry Smith   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
672d5ba7fb7SMatthew Knepley   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
673a2e34c3dSBarry Smith 
674*e350db43SBarry Smith   ierr = MatFDColoringViewFromOptions(coloring,"-mat_fd_coloring_view");CHKERRQ(ierr);
6753a40ed3dSBarry Smith   PetscFunctionReturn(0);
67643a90d84SBarry Smith }
677