xref: /petsc/src/mat/matfd/fdmatrix.c (revision 7d0a6c19129e7069c8a40e210b34ed62989173db)
1 
2 /*
3    This is where the abstract matrix operations are defined that are
4   used for finite difference computations of Jacobians using coloring.
5 */
6 
7 #include "private/matimpl.h"        /*I "petscmat.h" I*/
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "MatFDColoringSetF"
11 PetscErrorCode  MatFDColoringSetF(MatFDColoring fd,Vec F)
12 {
13   PetscFunctionBegin;
14   fd->F = F;
15   PetscFunctionReturn(0);
16 }
17 
18 #undef __FUNCT__
19 #define __FUNCT__ "MatFDColoringView_Draw_Zoom"
20 static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw,void *Aa)
21 {
22   MatFDColoring  fd = (MatFDColoring)Aa;
23   PetscErrorCode ierr;
24   PetscInt       i,j;
25   PetscReal      x,y;
26 
27   PetscFunctionBegin;
28 
29   /* loop over colors  */
30   for (i=0; i<fd->ncolors; i++) {
31     for (j=0; j<fd->nrows[i]; j++) {
32       y = fd->M - fd->rows[i][j] - fd->rstart;
33       x = fd->columnsforrow[i][j];
34       ierr = PetscDrawRectangle(draw,x,y,x+1,y+1,i+1,i+1,i+1,i+1);CHKERRQ(ierr);
35     }
36   }
37   PetscFunctionReturn(0);
38 }
39 
40 #undef __FUNCT__
41 #define __FUNCT__ "MatFDColoringView_Draw"
42 static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd,PetscViewer viewer)
43 {
44   PetscErrorCode ierr;
45   PetscBool      isnull;
46   PetscDraw      draw;
47   PetscReal      xr,yr,xl,yl,h,w;
48 
49   PetscFunctionBegin;
50   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
51   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0);
52 
53   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
54 
55   xr  = fd->N; yr = fd->M; h = yr/10.0; w = xr/10.0;
56   xr += w;     yr += h;    xl = -w;     yl = -h;
57   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
58   ierr = PetscDrawZoom(draw,MatFDColoringView_Draw_Zoom,fd);CHKERRQ(ierr);
59   ierr = PetscObjectCompose((PetscObject)fd,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
60   PetscFunctionReturn(0);
61 }
62 
63 #undef __FUNCT__
64 #define __FUNCT__ "MatFDColoringView"
65 /*@C
66    MatFDColoringView - Views a finite difference coloring context.
67 
68    Collective on MatFDColoring
69 
70    Input  Parameters:
71 +  c - the coloring context
72 -  viewer - visualization context
73 
74    Level: intermediate
75 
76    Notes:
77    The available visualization contexts include
78 +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
79 .     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
80         output where only the first processor opens
81         the file.  All other processors send their
82         data to the first processor to print.
83 -     PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure
84 
85    Notes:
86      Since PETSc uses only a small number of basic colors (currently 33), if the coloring
87    involves more than 33 then some seemingly identical colors are displayed making it look
88    like an illegal coloring. This is just a graphical artifact.
89 
90 .seealso: MatFDColoringCreate()
91 
92 .keywords: Mat, finite differences, coloring, view
93 @*/
94 PetscErrorCode  MatFDColoringView(MatFDColoring c,PetscViewer viewer)
95 {
96   PetscErrorCode    ierr;
97   PetscInt          i,j;
98   PetscBool         isdraw,iascii;
99   PetscViewerFormat format;
100 
101   PetscFunctionBegin;
102   PetscValidHeaderSpecific(c,MAT_FDCOLORING_CLASSID,1);
103   if (!viewer) {
104     ierr = PetscViewerASCIIGetStdout(((PetscObject)c)->comm,&viewer);CHKERRQ(ierr);
105   }
106   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
107   PetscCheckSameComm(c,1,viewer,2);
108 
109   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
110   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
111   if (isdraw) {
112     ierr = MatFDColoringView_Draw(c,viewer);CHKERRQ(ierr);
113   } else if (iascii) {
114     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)c,viewer,"MatFDColoring Object");CHKERRQ(ierr);
115     ierr = PetscViewerASCIIPrintf(viewer,"  Error tolerance=%G\n",c->error_rel);CHKERRQ(ierr);
116     ierr = PetscViewerASCIIPrintf(viewer,"  Umin=%G\n",c->umin);CHKERRQ(ierr);
117     ierr = PetscViewerASCIIPrintf(viewer,"  Number of colors=%D\n",c->ncolors);CHKERRQ(ierr);
118 
119     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
120     if (format != PETSC_VIEWER_ASCII_INFO) {
121       for (i=0; i<c->ncolors; i++) {
122         ierr = PetscViewerASCIIPrintf(viewer,"  Information for color %D\n",i);CHKERRQ(ierr);
123         ierr = PetscViewerASCIIPrintf(viewer,"    Number of columns %D\n",c->ncolumns[i]);CHKERRQ(ierr);
124         for (j=0; j<c->ncolumns[i]; j++) {
125           ierr = PetscViewerASCIIPrintf(viewer,"      %D\n",c->columns[i][j]);CHKERRQ(ierr);
126         }
127         ierr = PetscViewerASCIIPrintf(viewer,"    Number of rows %D\n",c->nrows[i]);CHKERRQ(ierr);
128         for (j=0; j<c->nrows[i]; j++) {
129           ierr = PetscViewerASCIIPrintf(viewer,"      %D %D \n",c->rows[i][j],c->columnsforrow[i][j]);CHKERRQ(ierr);
130         }
131       }
132     }
133     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
134   } else {
135     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for MatFDColoring",((PetscObject)viewer)->type_name);
136   }
137   PetscFunctionReturn(0);
138 }
139 
140 #undef __FUNCT__
141 #define __FUNCT__ "MatFDColoringSetParameters"
142 /*@
143    MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
144    a Jacobian matrix using finite differences.
145 
146    Logically Collective on MatFDColoring
147 
148    The Jacobian is estimated with the differencing approximation
149 .vb
150        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
151        h = error_rel*u[i]                 if  abs(u[i]) > umin
152          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
153        dx_{i} = (0, ... 1, .... 0)
154 .ve
155 
156    Input Parameters:
157 +  coloring - the coloring context
158 .  error_rel - relative error
159 -  umin - minimum allowable u-value magnitude
160 
161    Level: advanced
162 
163 .keywords: Mat, finite differences, coloring, set, parameters
164 
165 .seealso: MatFDColoringCreate(), MatFDColoringSetFromOptions()
166 
167 @*/
168 PetscErrorCode  MatFDColoringSetParameters(MatFDColoring matfd,PetscReal error,PetscReal umin)
169 {
170   PetscFunctionBegin;
171   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
172   PetscValidLogicalCollectiveReal(matfd,error,2);
173   PetscValidLogicalCollectiveReal(matfd,umin,3);
174   if (error != PETSC_DEFAULT) matfd->error_rel = error;
175   if (umin != PETSC_DEFAULT)  matfd->umin      = umin;
176   PetscFunctionReturn(0);
177 }
178 
179 
180 
181 #undef __FUNCT__
182 #define __FUNCT__ "MatFDColoringGetFunction"
183 /*@C
184    MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.
185 
186    Not Collective
187 
188    Input Parameters:
189 .  coloring - the coloring context
190 
191    Output Parameters:
192 +  f - the function
193 -  fctx - the optional user-defined function context
194 
195    Level: intermediate
196 
197 .keywords: Mat, Jacobian, finite differences, set, function
198 
199 .seealso: MatFDColoringCreate(), MatFDColoringSetFunction(), MatFDColoringSetFromOptions()
200 
201 @*/
202 PetscErrorCode  MatFDColoringGetFunction(MatFDColoring matfd,PetscErrorCode (**f)(void),void **fctx)
203 {
204   PetscFunctionBegin;
205   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
206   if (f) *f = matfd->f;
207   if (fctx) *fctx = matfd->fctx;
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "MatFDColoringSetFunction"
213 /*@C
214    MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
215 
216    Logically Collective on MatFDColoring
217 
218    Input Parameters:
219 +  coloring - the coloring context
220 .  f - the function
221 -  fctx - the optional user-defined function context
222 
223    Calling sequence of (*f) function:
224     For SNES:    PetscErrorCode (*f)(SNES,Vec,Vec,void*)
225     For TS:      PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*)
226     If not using SNES or TS: PetscErrorCode (*f)(void *dummy,Vec,Vec,void*) and dummy is ignored
227 
228    Level: advanced
229 
230    Notes: This function is usually used automatically by SNES or TS (when one uses SNESSetJacobian() with the argument
231      SNESDefaultComputeJacobianColor() or TSSetRHSJacobian() with the argument TSDefaultComputeJacobianColor()) and only needs to be used
232      by someone computing a matrix via coloring directly by calling MatFDColoringApply()
233 
234    Fortran Notes:
235     In Fortran you must call MatFDColoringSetFunction() for a coloring object to
236   be used without SNES or TS or within the SNES solvers and MatFDColoringSetFunctionTS() if it is to be used
237   within the TS solvers.
238 
239 .keywords: Mat, Jacobian, finite differences, set, function
240 
241 .seealso: MatFDColoringCreate(), MatFDColoringGetFunction(), MatFDColoringSetFromOptions()
242 
243 @*/
244 PetscErrorCode  MatFDColoringSetFunction(MatFDColoring matfd,PetscErrorCode (*f)(void),void *fctx)
245 {
246   PetscFunctionBegin;
247   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
248   matfd->f    = f;
249   matfd->fctx = fctx;
250   PetscFunctionReturn(0);
251 }
252 
253 #undef __FUNCT__
254 #define __FUNCT__ "MatFDColoringSetFromOptions"
255 /*@
256    MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
257    the options database.
258 
259    Collective on MatFDColoring
260 
261    The Jacobian, F'(u), is estimated with the differencing approximation
262 .vb
263        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
264        h = error_rel*u[i]                 if  abs(u[i]) > umin
265          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
266        dx_{i} = (0, ... 1, .... 0)
267 .ve
268 
269    Input Parameter:
270 .  coloring - the coloring context
271 
272    Options Database Keys:
273 +  -mat_fd_coloring_err <err> - Sets <err> (square root
274            of relative error in the function)
275 .  -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
276 .  -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
277 .  -mat_fd_coloring_view - Activates basic viewing
278 .  -mat_fd_coloring_view_info - Activates viewing info
279 -  -mat_fd_coloring_view_draw - Activates drawing
280 
281     Level: intermediate
282 
283 .keywords: Mat, finite differences, parameters
284 
285 .seealso: MatFDColoringCreate(), MatFDColoringView(), MatFDColoringSetParameters()
286 
287 @*/
288 PetscErrorCode  MatFDColoringSetFromOptions(MatFDColoring matfd)
289 {
290   PetscErrorCode ierr;
291   PetscBool      flg;
292   char           value[3];
293 
294   PetscFunctionBegin;
295   PetscValidHeaderSpecific(matfd,MAT_FDCOLORING_CLASSID,1);
296 
297   ierr = PetscOptionsBegin(((PetscObject)matfd)->comm,((PetscObject)matfd)->prefix,"Jacobian computation via finite differences option","MatFD");CHKERRQ(ierr);
298     ierr = PetscOptionsReal("-mat_fd_coloring_err","Square root of relative error in function","MatFDColoringSetParameters",matfd->error_rel,&matfd->error_rel,0);CHKERRQ(ierr);
299     ierr = PetscOptionsReal("-mat_fd_coloring_umin","Minimum allowable u magnitude","MatFDColoringSetParameters",matfd->umin,&matfd->umin,0);CHKERRQ(ierr);
300     ierr = PetscOptionsString("-mat_fd_type","Algorithm to compute h, wp or ds","MatFDColoringCreate",matfd->htype,value,3,&flg);CHKERRQ(ierr);
301     if (flg) {
302       if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
303       else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
304       else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown finite differencing type %s",value);
305     }
306     /* not used here; but so they are presented in the GUI */
307     ierr = PetscOptionsName("-mat_fd_coloring_view","Print entire datastructure used for Jacobian","None",0);CHKERRQ(ierr);
308     ierr = PetscOptionsName("-mat_fd_coloring_view_info","Print number of colors etc for Jacobian","None",0);CHKERRQ(ierr);
309     ierr = PetscOptionsName("-mat_fd_coloring_view_draw","Plot nonzero structure ofJacobian","None",0);CHKERRQ(ierr);
310 
311     /* process any options handlers added with PetscObjectAddOptionsHandler() */
312     ierr = PetscObjectProcessOptionsHandlers((PetscObject)matfd);CHKERRQ(ierr);
313   PetscOptionsEnd();CHKERRQ(ierr);
314   PetscFunctionReturn(0);
315 }
316 
317 #undef __FUNCT__
318 #define __FUNCT__ "MatFDColoringView_Private"
319 PetscErrorCode MatFDColoringView_Private(MatFDColoring fd)
320 {
321   PetscErrorCode ierr;
322   PetscBool      flg = PETSC_FALSE;
323   PetscViewer    viewer;
324 
325   PetscFunctionBegin;
326   ierr = PetscViewerASCIIGetStdout(((PetscObject)fd)->comm,&viewer);CHKERRQ(ierr);
327   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_view",&flg,PETSC_NULL);CHKERRQ(ierr);
328   if (flg) {
329     ierr = MatFDColoringView(fd,viewer);CHKERRQ(ierr);
330   }
331   flg  = PETSC_FALSE;
332   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_view_info",&flg,PETSC_NULL);CHKERRQ(ierr);
333   if (flg) {
334     ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
335     ierr = MatFDColoringView(fd,viewer);CHKERRQ(ierr);
336     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
337   }
338   flg  = PETSC_FALSE;
339   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_view_draw",&flg,PETSC_NULL);CHKERRQ(ierr);
340   if (flg) {
341     ierr = MatFDColoringView(fd,PETSC_VIEWER_DRAW_(((PetscObject)fd)->comm));CHKERRQ(ierr);
342     ierr = PetscViewerFlush(PETSC_VIEWER_DRAW_(((PetscObject)fd)->comm));CHKERRQ(ierr);
343   }
344   PetscFunctionReturn(0);
345 }
346 
347 #undef __FUNCT__
348 #define __FUNCT__ "MatFDColoringCreate"
349 /*@
350    MatFDColoringCreate - Creates a matrix coloring context for finite difference
351    computation of Jacobians.
352 
353    Collective on Mat
354 
355    Input Parameters:
356 +  mat - the matrix containing the nonzero structure of the Jacobian
357 -  iscoloring - the coloring of the matrix; usually obtained with MatGetColoring() or DMGetColoring()
358 
359     Output Parameter:
360 .   color - the new coloring context
361 
362     Level: intermediate
363 
364 .seealso: MatFDColoringDestroy(),SNESDefaultComputeJacobianColor(), ISColoringCreate(),
365           MatFDColoringSetFunction(), MatFDColoringSetFromOptions(), MatFDColoringApply(),
366           MatFDColoringView(), MatFDColoringSetParameters(), MatGetColoring(), DMGetColoring()
367 @*/
368 PetscErrorCode  MatFDColoringCreate(Mat mat,ISColoring iscoloring,MatFDColoring *color)
369 {
370   MatFDColoring  c;
371   MPI_Comm       comm;
372   PetscErrorCode ierr;
373   PetscInt       M,N;
374 
375   PetscFunctionBegin;
376   ierr = PetscLogEventBegin(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
377   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
378   if (M != N) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Only for square matrices");
379 
380   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
381   ierr = PetscHeaderCreate(c,_p_MatFDColoring,int,MAT_FDCOLORING_CLASSID,0,"MatFDColoring",comm,MatFDColoringDestroy,MatFDColoringView);CHKERRQ(ierr);
382 
383   c->ctype = iscoloring->ctype;
384 
385   if (mat->ops->fdcoloringcreate) {
386     ierr = (*mat->ops->fdcoloringcreate)(mat,iscoloring,c);CHKERRQ(ierr);
387   } else SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"Code not yet written for this matrix type");
388 
389   ierr = MatGetVecs(mat,PETSC_NULL,&c->w1);CHKERRQ(ierr);
390   ierr = PetscLogObjectParent(c,c->w1);CHKERRQ(ierr);
391   ierr = VecDuplicate(c->w1,&c->w2);CHKERRQ(ierr);
392   ierr = PetscLogObjectParent(c,c->w2);CHKERRQ(ierr);
393 
394   c->error_rel         = PETSC_SQRT_MACHINE_EPSILON;
395   c->umin              = 100.0*PETSC_SQRT_MACHINE_EPSILON;
396   c->currentcolor      = -1;
397   c->htype             = "wp";
398 
399   *color = c;
400   ierr = PetscLogEventEnd(MAT_FDColoringCreate,mat,0,0,0);CHKERRQ(ierr);
401   PetscFunctionReturn(0);
402 }
403 
404 #undef __FUNCT__
405 #define __FUNCT__ "MatFDColoringDestroy"
406 /*@
407     MatFDColoringDestroy - Destroys a matrix coloring context that was created
408     via MatFDColoringCreate().
409 
410     Collective on MatFDColoring
411 
412     Input Parameter:
413 .   c - coloring context
414 
415     Level: intermediate
416 
417 .seealso: MatFDColoringCreate()
418 @*/
419 PetscErrorCode  MatFDColoringDestroy(MatFDColoring c)
420 {
421   PetscErrorCode ierr;
422   PetscInt       i;
423 
424   PetscFunctionBegin;
425   if (--((PetscObject)c)->refct > 0) PetscFunctionReturn(0);
426 
427   for (i=0; i<c->ncolors; i++) {
428     ierr = PetscFree(c->columns[i]);CHKERRQ(ierr);
429     ierr = PetscFree(c->rows[i]);CHKERRQ(ierr);
430     ierr = PetscFree(c->columnsforrow[i]);CHKERRQ(ierr);
431     if (c->vscaleforrow) {ierr = PetscFree(c->vscaleforrow[i]);CHKERRQ(ierr);}
432   }
433   ierr = PetscFree(c->ncolumns);CHKERRQ(ierr);
434   ierr = PetscFree(c->columns);CHKERRQ(ierr);
435   ierr = PetscFree(c->nrows);CHKERRQ(ierr);
436   ierr = PetscFree(c->rows);CHKERRQ(ierr);
437   ierr = PetscFree(c->columnsforrow);CHKERRQ(ierr);
438   ierr = PetscFree(c->vscaleforrow);CHKERRQ(ierr);
439   if (c->vscale)       {ierr = VecDestroy(c->vscale);CHKERRQ(ierr);}
440   if (c->w1) {
441     ierr = VecDestroy(c->w1);CHKERRQ(ierr);
442     ierr = VecDestroy(c->w2);CHKERRQ(ierr);
443   }
444   if (c->w3){
445     ierr = VecDestroy(c->w3);CHKERRQ(ierr);
446   }
447   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
448   PetscFunctionReturn(0);
449 }
450 
451 #undef __FUNCT__
452 #define __FUNCT__ "MatFDColoringGetPerturbedColumns"
453 /*@C
454     MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
455       that are currently being perturbed.
456 
457     Not Collective
458 
459     Input Parameters:
460 .   coloring - coloring context created with MatFDColoringCreate()
461 
462     Output Parameters:
463 +   n - the number of local columns being perturbed
464 -   cols - the column indices, in global numbering
465 
466    Level: intermediate
467 
468 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringApply()
469 
470 .keywords: coloring, Jacobian, finite differences
471 @*/
472 PetscErrorCode  MatFDColoringGetPerturbedColumns(MatFDColoring coloring,PetscInt *n,PetscInt *cols[])
473 {
474   PetscFunctionBegin;
475   if (coloring->currentcolor >= 0) {
476     *n    = coloring->ncolumns[coloring->currentcolor];
477     *cols = coloring->columns[coloring->currentcolor];
478   } else {
479     *n = 0;
480   }
481   PetscFunctionReturn(0);
482 }
483 
484 #undef __FUNCT__
485 #define __FUNCT__ "MatFDColoringApply"
486 /*@
487     MatFDColoringApply - Given a matrix for which a MatFDColoring context
488     has been created, computes the Jacobian for a function via finite differences.
489 
490     Collective on MatFDColoring
491 
492     Input Parameters:
493 +   mat - location to store Jacobian
494 .   coloring - coloring context created with MatFDColoringCreate()
495 .   x1 - location at which Jacobian is to be computed
496 -   sctx - context required by function, if this is being used with the SNES solver then it is SNES object, otherwise it is null
497 
498     Options Database Keys:
499 +    -mat_fd_type - "wp" or "ds"  (see MATMFFD_WP or MATMFFD_DS)
500 .    -mat_fd_coloring_view - Activates basic viewing or coloring
501 .    -mat_fd_coloring_view_draw - Activates drawing of coloring
502 -    -mat_fd_coloring_view_info - Activates viewing of coloring info
503 
504     Level: intermediate
505 
506 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction()
507 
508 .keywords: coloring, Jacobian, finite differences
509 @*/
510 PetscErrorCode  MatFDColoringApply(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
511 {
512   PetscErrorCode ierr;
513 
514   PetscFunctionBegin;
515   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
516   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
517   PetscValidHeaderSpecific(x1,VEC_CLASSID,3);
518   if (!coloring->f) SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
519   if (!J->ops->fdcoloringapply) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not supported for this matrix type %s",((PetscObject)J)->type_name);
520   ierr = (*J->ops->fdcoloringapply)(J,coloring,x1,flag,sctx);CHKERRQ(ierr);
521   PetscFunctionReturn(0);
522 }
523 
524 #undef __FUNCT__
525 #define __FUNCT__ "MatFDColoringApply_AIJ"
526 PetscErrorCode  MatFDColoringApply_AIJ(Mat J,MatFDColoring coloring,Vec x1,MatStructure *flag,void *sctx)
527 {
528   PetscErrorCode (*f)(void*,Vec,Vec,void*) = (PetscErrorCode (*)(void*,Vec,Vec,void *))coloring->f;
529   PetscErrorCode ierr;
530   PetscInt       k,start,end,l,row,col,srow,**vscaleforrow,m1,m2;
531   PetscScalar    dx,*y,*xx,*w3_array;
532   PetscScalar    *vscale_array;
533   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin,unorm;
534   Vec            w1=coloring->w1,w2=coloring->w2,w3;
535   void           *fctx = coloring->fctx;
536   PetscBool      flg = PETSC_FALSE;
537   PetscInt       ctype=coloring->ctype,N,col_start=0,col_end=0;
538   Vec            x1_tmp;
539 
540   PetscFunctionBegin;
541   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
542   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
543   PetscValidHeaderSpecific(x1,VEC_CLASSID,3);
544   if (!f) SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_WRONGSTATE,"Must call MatFDColoringSetFunction()");
545 
546   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
547   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
548   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr);
549   if (flg) {
550     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
551   } else {
552     PetscBool  assembled;
553     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
554     if (assembled) {
555       ierr = MatZeroEntries(J);CHKERRQ(ierr);
556     }
557   }
558 
559   x1_tmp = x1;
560   if (!coloring->vscale){
561     ierr = VecDuplicate(x1_tmp,&coloring->vscale);CHKERRQ(ierr);
562   }
563 
564   /*
565     This is a horrible, horrible, hack. See DMMGComputeJacobian_Multigrid() it inproperly sets
566     coloring->F for the coarser grids from the finest
567   */
568   if (coloring->F) {
569     ierr = VecGetLocalSize(coloring->F,&m1);CHKERRQ(ierr);
570     ierr = VecGetLocalSize(w1,&m2);CHKERRQ(ierr);
571     if (m1 != m2) {
572       coloring->F = 0;
573       }
574     }
575 
576   if (coloring->htype[0] == 'w') { /* tacky test; need to make systematic if we add other approaches to computing h*/
577     ierr = VecNorm(x1_tmp,NORM_2,&unorm);CHKERRQ(ierr);
578   }
579   ierr = VecGetOwnershipRange(w1,&start,&end);CHKERRQ(ierr); /* OwnershipRange is used by ghosted x! */
580 
581   /* Set w1 = F(x1) */
582   if (coloring->F) {
583     w1          = coloring->F; /* use already computed value of function */
584     coloring->F = 0;
585   } else {
586     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
587     ierr = (*f)(sctx,x1_tmp,w1,fctx);CHKERRQ(ierr);
588     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
589   }
590 
591   if (!coloring->w3) {
592     ierr = VecDuplicate(x1_tmp,&coloring->w3);CHKERRQ(ierr);
593     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
594   }
595   w3 = coloring->w3;
596 
597     /* Compute all the local scale factors, including ghost points */
598   ierr = VecGetLocalSize(x1_tmp,&N);CHKERRQ(ierr);
599   ierr = VecGetArray(x1_tmp,&xx);CHKERRQ(ierr);
600   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
601   if (ctype == IS_COLORING_GHOSTED){
602     col_start = 0; col_end = N;
603   } else if (ctype == IS_COLORING_GLOBAL){
604     xx = xx - start;
605     vscale_array = vscale_array - start;
606     col_start = start; col_end = N + start;
607   }
608   for (col=col_start; col<col_end; col++){
609     /* Loop over each local column, vscale[col] = 1./(epsilon*dx[col]) */
610     if (coloring->htype[0] == 'w') {
611       dx = 1.0 + unorm;
612     } else {
613       dx  = xx[col];
614     }
615     if (dx == 0.0) dx = 1.0;
616 #if !defined(PETSC_USE_COMPLEX)
617     if (dx < umin && dx >= 0.0)      dx = umin;
618     else if (dx < 0.0 && dx > -umin) dx = -umin;
619 #else
620     if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
621     else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
622 #endif
623     dx               *= epsilon;
624     vscale_array[col] = 1.0/dx;
625   }
626   if (ctype == IS_COLORING_GLOBAL)  vscale_array = vscale_array + start;
627   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
628   if (ctype == IS_COLORING_GLOBAL){
629     ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
630     ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
631   }
632 
633   if (coloring->vscaleforrow) {
634     vscaleforrow = coloring->vscaleforrow;
635   } else SETERRQ(((PetscObject)J)->comm,PETSC_ERR_ARG_NULL,"Null Object: coloring->vscaleforrow");
636 
637   /*
638     Loop over each color
639   */
640   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
641   for (k=0; k<coloring->ncolors; k++) {
642     coloring->currentcolor = k;
643     ierr = VecCopy(x1_tmp,w3);CHKERRQ(ierr);
644     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);
645     if (ctype == IS_COLORING_GLOBAL) w3_array = w3_array - start;
646     /*
647       Loop over each column associated with color
648       adding the perturbation to the vector w3.
649     */
650     for (l=0; l<coloring->ncolumns[k]; l++) {
651       col = coloring->columns[k][l];    /* local column of the matrix we are probing for */
652       if (coloring->htype[0] == 'w') {
653         dx = 1.0 + unorm;
654       } else {
655         dx  = xx[col];
656       }
657       if (dx == 0.0) dx = 1.0;
658 #if !defined(PETSC_USE_COMPLEX)
659       if (dx < umin && dx >= 0.0)      dx = umin;
660       else if (dx < 0.0 && dx > -umin) dx = -umin;
661 #else
662       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
663       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
664 #endif
665       dx            *= epsilon;
666       if (!PetscAbsScalar(dx)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed 0 differencing parameter");
667       w3_array[col] += dx;
668     }
669     if (ctype == IS_COLORING_GLOBAL) w3_array = w3_array + start;
670     ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
671 
672     /*
673       Evaluate function at w3 = x1 + dx (here dx is a vector of perturbations)
674                            w2 = F(x1 + dx) - F(x1)
675     */
676     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
677     ierr = (*f)(sctx,w3,w2,fctx);CHKERRQ(ierr);
678     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
679     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
680 
681     /*
682       Loop over rows of vector, putting results into Jacobian matrix
683     */
684     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
685     for (l=0; l<coloring->nrows[k]; l++) {
686       row    = coloring->rows[k][l];             /* local row index */
687       col    = coloring->columnsforrow[k][l];    /* global column index */
688       y[row] *= vscale_array[vscaleforrow[k][l]];
689       srow   = row + start;
690       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
691     }
692     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
693   } /* endof for each color */
694   if (ctype == IS_COLORING_GLOBAL) xx = xx + start;
695   ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
696   ierr = VecRestoreArray(x1_tmp,&xx);CHKERRQ(ierr);
697 
698   coloring->currentcolor = -1;
699   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
700   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
701   ierr = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
702 
703   flg  = PETSC_FALSE;
704   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_null_space_test",&flg,PETSC_NULL);CHKERRQ(ierr);
705   if (flg) {
706     ierr = MatNullSpaceTest(J->nullsp,J,PETSC_NULL);CHKERRQ(ierr);
707   }
708   ierr = MatFDColoringView_Private(coloring);CHKERRQ(ierr);
709   PetscFunctionReturn(0);
710 }
711 
712 #undef __FUNCT__
713 #define __FUNCT__ "MatFDColoringApplyTS"
714 /*@
715     MatFDColoringApplyTS - Given a matrix for which a MatFDColoring context
716     has been created, computes the Jacobian for a function via finite differences.
717 
718    Collective on Mat, MatFDColoring, and Vec
719 
720     Input Parameters:
721 +   mat - location to store Jacobian
722 .   coloring - coloring context created with MatFDColoringCreate()
723 .   x1 - location at which Jacobian is to be computed
724 -   sctx - context required by function, if this is being used with the TS solver then it is TS object, otherwise it is null
725 
726    Level: intermediate
727 
728 .seealso: MatFDColoringCreate(), MatFDColoringDestroy(), MatFDColoringView(), MatFDColoringSetFunction()
729 
730 .keywords: coloring, Jacobian, finite differences
731 @*/
732 PetscErrorCode  MatFDColoringApplyTS(Mat J,MatFDColoring coloring,PetscReal t,Vec x1,MatStructure *flag,void *sctx)
733 {
734   PetscErrorCode (*f)(void*,PetscReal,Vec,Vec,void*)=(PetscErrorCode (*)(void*,PetscReal,Vec,Vec,void *))coloring->f;
735   PetscErrorCode ierr;
736   PetscInt       k,N,start,end,l,row,col,srow,**vscaleforrow;
737   PetscScalar    dx,*y,*xx,*w3_array;
738   PetscScalar    *vscale_array;
739   PetscReal      epsilon = coloring->error_rel,umin = coloring->umin;
740   Vec            w1=coloring->w1,w2=coloring->w2,w3;
741   void           *fctx = coloring->fctx;
742   PetscBool      flg;
743 
744   PetscFunctionBegin;
745   PetscValidHeaderSpecific(J,MAT_CLASSID,1);
746   PetscValidHeaderSpecific(coloring,MAT_FDCOLORING_CLASSID,2);
747   PetscValidHeaderSpecific(x1,VEC_CLASSID,4);
748 
749   ierr = PetscLogEventBegin(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
750   if (!coloring->w3) {
751     ierr = VecDuplicate(x1,&coloring->w3);CHKERRQ(ierr);
752     ierr = PetscLogObjectParent(coloring,coloring->w3);CHKERRQ(ierr);
753   }
754   w3 = coloring->w3;
755 
756   ierr = MatSetUnfactored(J);CHKERRQ(ierr);
757   flg  = PETSC_FALSE;
758   ierr = PetscOptionsGetBool(PETSC_NULL,"-mat_fd_coloring_dont_rezero",&flg,PETSC_NULL);CHKERRQ(ierr);
759   if (flg) {
760     ierr = PetscInfo(coloring,"Not calling MatZeroEntries()\n");CHKERRQ(ierr);
761   } else {
762     PetscBool  assembled;
763     ierr = MatAssembled(J,&assembled);CHKERRQ(ierr);
764     if (assembled) {
765       ierr = MatZeroEntries(J);CHKERRQ(ierr);
766     }
767   }
768 
769   ierr = VecGetOwnershipRange(x1,&start,&end);CHKERRQ(ierr);
770   ierr = VecGetSize(x1,&N);CHKERRQ(ierr);
771   ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
772   ierr = (*f)(sctx,t,x1,w1,fctx);CHKERRQ(ierr);
773   ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
774 
775   /*
776       Compute all the scale factors and share with other processors
777   */
778   ierr = VecGetArray(x1,&xx);CHKERRQ(ierr);xx = xx - start;
779   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);vscale_array = vscale_array - start;
780   for (k=0; k<coloring->ncolors; k++) {
781     /*
782        Loop over each column associated with color adding the
783        perturbation to the vector w3.
784     */
785     for (l=0; l<coloring->ncolumns[k]; l++) {
786       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
787       dx  = xx[col];
788       if (dx == 0.0) dx = 1.0;
789 #if !defined(PETSC_USE_COMPLEX)
790       if (dx < umin && dx >= 0.0)      dx = umin;
791       else if (dx < 0.0 && dx > -umin) dx = -umin;
792 #else
793       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
794       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
795 #endif
796       dx                *= epsilon;
797       vscale_array[col] = 1.0/dx;
798     }
799   }
800   vscale_array = vscale_array - start;ierr = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
801   ierr = VecGhostUpdateBegin(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
802   ierr = VecGhostUpdateEnd(coloring->vscale,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
803 
804   if (coloring->vscaleforrow) vscaleforrow = coloring->vscaleforrow;
805   else                        vscaleforrow = coloring->columnsforrow;
806 
807   ierr = VecGetArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
808   /*
809       Loop over each color
810   */
811   for (k=0; k<coloring->ncolors; k++) {
812     ierr = VecCopy(x1,w3);CHKERRQ(ierr);
813     ierr = VecGetArray(w3,&w3_array);CHKERRQ(ierr);w3_array = w3_array - start;
814     /*
815        Loop over each column associated with color adding the
816        perturbation to the vector w3.
817     */
818     for (l=0; l<coloring->ncolumns[k]; l++) {
819       col = coloring->columns[k][l];    /* column of the matrix we are probing for */
820       dx  = xx[col];
821       if (dx == 0.0) dx = 1.0;
822 #if !defined(PETSC_USE_COMPLEX)
823       if (dx < umin && dx >= 0.0)      dx = umin;
824       else if (dx < 0.0 && dx > -umin) dx = -umin;
825 #else
826       if (PetscAbsScalar(dx) < umin && PetscRealPart(dx) >= 0.0)     dx = umin;
827       else if (PetscRealPart(dx) < 0.0 && PetscAbsScalar(dx) < umin) dx = -umin;
828 #endif
829       dx            *= epsilon;
830       w3_array[col] += dx;
831     }
832     w3_array = w3_array + start; ierr = VecRestoreArray(w3,&w3_array);CHKERRQ(ierr);
833 
834     /*
835        Evaluate function at x1 + dx (here dx is a vector of perturbations)
836     */
837     ierr = PetscLogEventBegin(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
838     ierr = (*f)(sctx,t,w3,w2,fctx);CHKERRQ(ierr);
839     ierr = PetscLogEventEnd(MAT_FDColoringFunction,0,0,0,0);CHKERRQ(ierr);
840     ierr = VecAXPY(w2,-1.0,w1);CHKERRQ(ierr);
841 
842     /*
843        Loop over rows of vector, putting results into Jacobian matrix
844     */
845     ierr = VecGetArray(w2,&y);CHKERRQ(ierr);
846     for (l=0; l<coloring->nrows[k]; l++) {
847       row    = coloring->rows[k][l];
848       col    = coloring->columnsforrow[k][l];
849       y[row] *= vscale_array[vscaleforrow[k][l]];
850       srow   = row + start;
851       ierr   = MatSetValues(J,1,&srow,1,&col,y+row,INSERT_VALUES);CHKERRQ(ierr);
852     }
853     ierr = VecRestoreArray(w2,&y);CHKERRQ(ierr);
854   }
855   ierr  = VecRestoreArray(coloring->vscale,&vscale_array);CHKERRQ(ierr);
856   xx    = xx + start; ierr  = VecRestoreArray(x1,&xx);CHKERRQ(ierr);
857   ierr  = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
858   ierr  = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
859   ierr  = PetscLogEventEnd(MAT_FDColoringApply,coloring,J,x1,0);CHKERRQ(ierr);
860   PetscFunctionReturn(0);
861 }
862 
863 
864 
865