Actual source code: fdmatrix.c
2: /*
3: This is where the abstract matrix operations are defined that are
4: used for finite difference computations of Jacobians using coloring.
5: */
7: #include <petsc/private/matimpl.h>
8: #include <petsc/private/isimpl.h>
10: PetscErrorCode MatFDColoringSetF(MatFDColoring fd, Vec F)
11: {
12: PetscFunctionBegin;
13: if (F) {
14: PetscCall(VecCopy(F, fd->w1));
15: fd->fset = PETSC_TRUE;
16: } else {
17: fd->fset = PETSC_FALSE;
18: }
19: PetscFunctionReturn(PETSC_SUCCESS);
20: }
22: #include <petscdraw.h>
23: static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw, void *Aa)
24: {
25: MatFDColoring fd = (MatFDColoring)Aa;
26: PetscInt i, j, nz, row;
27: PetscReal x, y;
28: MatEntry *Jentry = fd->matentry;
30: PetscFunctionBegin;
31: /* loop over colors */
32: nz = 0;
33: for (i = 0; i < fd->ncolors; i++) {
34: for (j = 0; j < fd->nrows[i]; j++) {
35: row = Jentry[nz].row;
36: y = fd->M - row - fd->rstart;
37: x = (PetscReal)Jentry[nz++].col;
38: PetscCall(PetscDrawRectangle(draw, x, y, x + 1, y + 1, i + 1, i + 1, i + 1, i + 1));
39: }
40: }
41: PetscFunctionReturn(PETSC_SUCCESS);
42: }
44: static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd, PetscViewer viewer)
45: {
46: PetscBool isnull;
47: PetscDraw draw;
48: PetscReal xr, yr, xl, yl, h, w;
50: PetscFunctionBegin;
51: PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
52: PetscCall(PetscDrawIsNull(draw, &isnull));
53: if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
55: xr = fd->N;
56: yr = fd->M;
57: h = yr / 10.0;
58: w = xr / 10.0;
59: xr += w;
60: yr += h;
61: xl = -w;
62: yl = -h;
63: PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
64: PetscCall(PetscObjectCompose((PetscObject)fd, "Zoomviewer", (PetscObject)viewer));
65: PetscCall(PetscDrawZoom(draw, MatFDColoringView_Draw_Zoom, fd));
66: PetscCall(PetscObjectCompose((PetscObject)fd, "Zoomviewer", NULL));
67: PetscCall(PetscDrawSave(draw));
68: PetscFunctionReturn(PETSC_SUCCESS);
69: }
71: /*@C
72: MatFDColoringView - Views a finite difference coloring context.
74: Collective
76: Input Parameters:
77: + c - the coloring context
78: - viewer - visualization context
80: Level: intermediate
82: Notes:
83: The available visualization contexts include
84: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
85: . `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
86: output where only the first processor opens
87: the file. All other processors send their
88: data to the first processor to print.
89: - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
91: Since PETSc uses only a small number of basic colors (currently 33), if the coloring
92: involves more than 33 then some seemingly identical colors are displayed making it look
93: like an illegal coloring. This is just a graphical artifact.
95: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`
96: @*/
97: PetscErrorCode MatFDColoringView(MatFDColoring c, PetscViewer viewer)
98: {
99: PetscInt i, j;
100: PetscBool isdraw, iascii;
101: PetscViewerFormat format;
103: PetscFunctionBegin;
105: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c), &viewer));
107: PetscCheckSameComm(c, 1, viewer, 2);
109: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
110: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
111: if (isdraw) {
112: PetscCall(MatFDColoringView_Draw(c, viewer));
113: } else if (iascii) {
114: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)c, viewer));
115: PetscCall(PetscViewerASCIIPrintf(viewer, " Error tolerance=%g\n", (double)c->error_rel));
116: PetscCall(PetscViewerASCIIPrintf(viewer, " Umin=%g\n", (double)c->umin));
117: PetscCall(PetscViewerASCIIPrintf(viewer, " Number of colors=%" PetscInt_FMT "\n", c->ncolors));
119: PetscCall(PetscViewerGetFormat(viewer, &format));
120: if (format != PETSC_VIEWER_ASCII_INFO) {
121: PetscInt row, col, nz;
122: nz = 0;
123: for (i = 0; i < c->ncolors; i++) {
124: PetscCall(PetscViewerASCIIPrintf(viewer, " Information for color %" PetscInt_FMT "\n", i));
125: PetscCall(PetscViewerASCIIPrintf(viewer, " Number of columns %" PetscInt_FMT "\n", c->ncolumns[i]));
126: for (j = 0; j < c->ncolumns[i]; j++) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "\n", c->columns[i][j]));
127: PetscCall(PetscViewerASCIIPrintf(viewer, " Number of rows %" PetscInt_FMT "\n", c->nrows[i]));
128: if (c->matentry) {
129: for (j = 0; j < c->nrows[i]; j++) {
130: row = c->matentry[nz].row;
131: col = c->matentry[nz++].col;
132: PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " %" PetscInt_FMT " \n", row, col));
133: }
134: }
135: }
136: }
137: PetscCall(PetscViewerFlush(viewer));
138: }
139: PetscFunctionReturn(PETSC_SUCCESS);
140: }
142: /*@
143: MatFDColoringSetParameters - Sets the parameters for the sparse approximation of
144: a Jacobian matrix using finite differences.
146: Logically Collective
148: Input Parameters:
149: + matfd - the coloring context
150: . error - relative error
151: - umin - minimum allowable u-value magnitude
153: Level: advanced
155: Note:
156: The Jacobian is estimated with the differencing approximation
157: .vb
158: F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
159: htype = 'ds':
160: h = error_rel*u[i] if abs(u[i]) > umin
161: = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i]
162: dx_{i} = (0, ... 1, .... 0)
164: htype = 'wp':
165: h = error_rel * sqrt(1 + ||u||)
166: .ve
168: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringSetFromOptions()`
169: @*/
170: PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd, PetscReal error, PetscReal umin)
171: {
172: PetscFunctionBegin;
176: if (error != (PetscReal)PETSC_DEFAULT) matfd->error_rel = error;
177: if (umin != (PetscReal)PETSC_DEFAULT) matfd->umin = umin;
178: PetscFunctionReturn(PETSC_SUCCESS);
179: }
181: /*@
182: MatFDColoringSetBlockSize - Sets block size for efficient inserting entries of Jacobian matrix.
184: Logically Collective
186: Input Parameters:
187: + coloring - the coloring context
188: . brows - number of rows in the block
189: - bcols - number of columns in the block
191: Level: intermediate
193: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringSetFromOptions()`
194: @*/
195: PetscErrorCode MatFDColoringSetBlockSize(MatFDColoring matfd, PetscInt brows, PetscInt bcols)
196: {
197: PetscFunctionBegin;
201: if (brows != PETSC_DEFAULT) matfd->brows = brows;
202: if (bcols != PETSC_DEFAULT) matfd->bcols = bcols;
203: PetscFunctionReturn(PETSC_SUCCESS);
204: }
206: /*@
207: MatFDColoringSetUp - Sets up the internal data structures of matrix coloring context for the later use.
209: Collective
211: Input Parameters:
212: + mat - the matrix containing the nonzero structure of the Jacobian
213: . iscoloring - the coloring of the matrix; usually obtained with `MatGetColoring()` or `DMCreateColoring()`
214: - color - the matrix coloring context
216: Level: beginner
218: Notes:
219: When the coloring type is `IS_COLORING_LOCAL` the coloring is in the local ordering of the unknowns.
221: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringDestroy()`
222: @*/
223: PetscErrorCode MatFDColoringSetUp(Mat mat, ISColoring iscoloring, MatFDColoring color)
224: {
225: PetscBool eq;
227: PetscFunctionBegin;
230: if (color->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
231: PetscCall(PetscObjectCompareId((PetscObject)mat, color->matid, &eq));
232: PetscCheck(eq, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix used with MatFDColoringSetUp() must be that used with MatFDColoringCreate()");
234: PetscCall(PetscLogEventBegin(MAT_FDColoringSetUp, mat, 0, 0, 0));
235: PetscUseTypeMethod(mat, fdcoloringsetup, iscoloring, color);
237: color->setupcalled = PETSC_TRUE;
238: PetscCall(PetscLogEventEnd(MAT_FDColoringSetUp, mat, 0, 0, 0));
239: PetscFunctionReturn(PETSC_SUCCESS);
240: }
242: /*@C
243: MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.
245: Not Collective
247: Input Parameter:
248: . coloring - the coloring context
250: Output Parameters:
251: + f - the function
252: - fctx - the optional user-defined function context
254: Level: intermediate
256: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`, `MatFDColoringSetFromOptions()`
257: @*/
258: PetscErrorCode MatFDColoringGetFunction(MatFDColoring matfd, PetscErrorCode (**f)(void), void **fctx)
259: {
260: PetscFunctionBegin;
262: if (f) *f = matfd->f;
263: if (fctx) *fctx = matfd->fctx;
264: PetscFunctionReturn(PETSC_SUCCESS);
265: }
267: /*@C
268: MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.
270: Logically Collective
272: Input Parameters:
273: + coloring - the coloring context
274: . f - the function
275: - fctx - the optional user-defined function context
277: Calling sequence with `SNES` of `f`:
278: $ PetscErrorCode f(SNES, Vec in, Vec out, void *fctx)
280: Calling sequence without `SNES` of `f`:
281: $ PetscErrorCode f(void *dummy, Vec in, Vec out, void *fctx)
283: Level: advanced
285: Note:
286: This function is usually used automatically by `SNES` (when one uses `SNESSetJacobian()` with the argument
287: `SNESComputeJacobianDefaultColor()`) and only needs to be used by someone computing a matrix via coloring directly by
288: calling `MatFDColoringApply()`
290: Fortran Note:
291: In Fortran you must call `MatFDColoringSetFunction()` for a coloring object to
292: be used without `SNES` or within the `SNES` solvers.
294: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringGetFunction()`, `MatFDColoringSetFromOptions()`
295: @*/
296: PetscErrorCode MatFDColoringSetFunction(MatFDColoring matfd, PetscErrorCode (*f)(void), void *fctx)
297: {
298: PetscFunctionBegin;
300: matfd->f = f;
301: matfd->fctx = fctx;
302: PetscFunctionReturn(PETSC_SUCCESS);
303: }
305: /*@
306: MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
307: the options database.
309: Collective
311: The Jacobian, F'(u), is estimated with the differencing approximation
312: .vb
313: F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
314: h = error_rel*u[i] if abs(u[i]) > umin
315: = +/- error_rel*umin otherwise, with +/- determined by the sign of u[i]
316: dx_{i} = (0, ... 1, .... 0)
317: .ve
319: Input Parameter:
320: . coloring - the coloring context
322: Options Database Keys:
323: + -mat_fd_coloring_err <err> - Sets <err> (square root of relative error in the function)
324: . -mat_fd_coloring_umin <umin> - Sets umin, the minimum allowable u-value magnitude
325: . -mat_fd_type - "wp" or "ds" (see MATMFFD_WP or MATMFFD_DS)
326: . -mat_fd_coloring_view - Activates basic viewing
327: . -mat_fd_coloring_view ::ascii_info - Activates viewing info
328: - -mat_fd_coloring_view draw - Activates drawing
330: Level: intermediate
332: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringView()`, `MatFDColoringSetParameters()`
333: @*/
334: PetscErrorCode MatFDColoringSetFromOptions(MatFDColoring matfd)
335: {
336: PetscBool flg;
337: char value[3];
339: PetscFunctionBegin;
342: PetscObjectOptionsBegin((PetscObject)matfd);
343: PetscCall(PetscOptionsReal("-mat_fd_coloring_err", "Square root of relative error in function", "MatFDColoringSetParameters", matfd->error_rel, &matfd->error_rel, NULL));
344: PetscCall(PetscOptionsReal("-mat_fd_coloring_umin", "Minimum allowable u magnitude", "MatFDColoringSetParameters", matfd->umin, &matfd->umin, NULL));
345: PetscCall(PetscOptionsString("-mat_fd_type", "Algorithm to compute h, wp or ds", "MatFDColoringCreate", matfd->htype, value, sizeof(value), &flg));
346: if (flg) {
347: if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
348: else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
349: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown finite differencing type %s", value);
350: }
351: PetscCall(PetscOptionsInt("-mat_fd_coloring_brows", "Number of block rows", "MatFDColoringSetBlockSize", matfd->brows, &matfd->brows, NULL));
352: PetscCall(PetscOptionsInt("-mat_fd_coloring_bcols", "Number of block columns", "MatFDColoringSetBlockSize", matfd->bcols, &matfd->bcols, &flg));
353: if (flg && matfd->bcols > matfd->ncolors) {
354: /* input bcols cannot be > matfd->ncolors, thus set it as ncolors */
355: matfd->bcols = matfd->ncolors;
356: }
358: /* process any options handlers added with PetscObjectAddOptionsHandler() */
359: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)matfd, PetscOptionsObject));
360: PetscOptionsEnd();
361: PetscFunctionReturn(PETSC_SUCCESS);
362: }
364: /*@C
365: MatFDColoringSetType - Sets the approach for computing the finite difference parameter
367: Collective
369: Input Parameters:
370: + coloring - the coloring context
371: - type - either `MATMFFD_WP` or `MATMFFD_DS`
373: Options Database Key:
374: . -mat_fd_type - "wp" or "ds"
376: Level: intermediate
378: Note:
379: It is goofy that the argument type is `MatMFFDType` since the `MatFDColoring` actually computes the matrix entries
380: but the process of computing the entries is the same as as with the `MATMFFD` operation so we should reuse the names instead of
381: introducing another one.
383: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringView()`, `MatFDColoringSetParameters()`
384: @*/
385: PetscErrorCode MatFDColoringSetType(MatFDColoring matfd, MatMFFDType type)
386: {
387: PetscFunctionBegin;
389: /*
390: It is goofy to handle the strings this way but currently there is no code to free a dynamically created matfd->htype
391: and this function is being provided as patch for a release so it shouldn't change the implementation
392: */
393: if (type[0] == 'w' && type[1] == 'p') matfd->htype = "wp";
394: else if (type[0] == 'd' && type[1] == 's') matfd->htype = "ds";
395: else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown finite differencing type %s", type);
396: PetscFunctionReturn(PETSC_SUCCESS);
397: }
399: PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd, const char prefix[], const char optionname[])
400: {
401: PetscBool flg;
402: PetscViewer viewer;
403: PetscViewerFormat format;
405: PetscFunctionBegin;
406: if (prefix) {
407: PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd), ((PetscObject)fd)->options, prefix, optionname, &viewer, &format, &flg));
408: } else {
409: PetscCall(PetscOptionsGetViewer(PetscObjectComm((PetscObject)fd), ((PetscObject)fd)->options, ((PetscObject)fd)->prefix, optionname, &viewer, &format, &flg));
410: }
411: if (flg) {
412: PetscCall(PetscViewerPushFormat(viewer, format));
413: PetscCall(MatFDColoringView(fd, viewer));
414: PetscCall(PetscViewerPopFormat(viewer));
415: PetscCall(PetscViewerDestroy(&viewer));
416: }
417: PetscFunctionReturn(PETSC_SUCCESS);
418: }
420: /*@
421: MatFDColoringCreate - Creates a matrix coloring context for finite difference
422: computation of Jacobians.
424: Collective
426: Input Parameters:
427: + mat - the matrix containing the nonzero structure of the Jacobian
428: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
430: Output Parameter:
431: . color - the new coloring context
433: Level: intermediate
435: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringDestroy()`, `SNESComputeJacobianDefaultColor()`, `ISColoringCreate()`,
436: `MatFDColoringSetFunction()`, `MatFDColoringSetFromOptions()`, `MatFDColoringApply()`,
437: `MatFDColoringView()`, `MatFDColoringSetParameters()`, `MatColoringCreate()`, `DMCreateColoring()`, `MatFDColoringSetValues()`
438: @*/
439: PetscErrorCode MatFDColoringCreate(Mat mat, ISColoring iscoloring, MatFDColoring *color)
440: {
441: MatFDColoring c;
442: MPI_Comm comm;
443: PetscInt M, N;
445: PetscFunctionBegin;
447: PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be assembled by calls to MatAssemblyBegin/End();");
448: PetscCall(PetscLogEventBegin(MAT_FDColoringCreate, mat, 0, 0, 0));
449: PetscCall(MatGetSize(mat, &M, &N));
450: PetscCheck(M == N, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Only for square matrices");
451: PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
452: PetscCall(PetscHeaderCreate(c, MAT_FDCOLORING_CLASSID, "MatFDColoring", "Jacobian computation via finite differences with coloring", "Mat", comm, MatFDColoringDestroy, MatFDColoringView));
454: c->ctype = iscoloring->ctype;
455: PetscCall(PetscObjectGetId((PetscObject)mat, &c->matid));
457: PetscUseTypeMethod(mat, fdcoloringcreate, iscoloring, c);
459: PetscCall(MatCreateVecs(mat, NULL, &c->w1));
460: /* Vec is used intensively in particular piece of scalar CPU code; won't benefit from bouncing back and forth to the GPU */
461: PetscCall(VecBindToCPU(c->w1, PETSC_TRUE));
462: PetscCall(VecDuplicate(c->w1, &c->w2));
463: /* Vec is used intensively in particular piece of scalar CPU code; won't benefit from bouncing back and forth to the GPU */
464: PetscCall(VecBindToCPU(c->w2, PETSC_TRUE));
466: c->error_rel = PETSC_SQRT_MACHINE_EPSILON;
467: c->umin = 100.0 * PETSC_SQRT_MACHINE_EPSILON;
468: c->currentcolor = -1;
469: c->htype = "wp";
470: c->fset = PETSC_FALSE;
471: c->setupcalled = PETSC_FALSE;
473: *color = c;
474: PetscCall(PetscObjectCompose((PetscObject)mat, "SNESMatFDColoring", (PetscObject)c));
475: PetscCall(PetscLogEventEnd(MAT_FDColoringCreate, mat, 0, 0, 0));
476: PetscFunctionReturn(PETSC_SUCCESS);
477: }
479: /*@
480: MatFDColoringDestroy - Destroys a matrix coloring context that was created
481: via `MatFDColoringCreate()`.
483: Collective
485: Input Parameter:
486: . c - coloring context
488: Level: intermediate
490: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`
491: @*/
492: PetscErrorCode MatFDColoringDestroy(MatFDColoring *c)
493: {
494: PetscInt i;
495: MatFDColoring color = *c;
497: PetscFunctionBegin;
498: if (!*c) PetscFunctionReturn(PETSC_SUCCESS);
499: if (--((PetscObject)color)->refct > 0) {
500: *c = NULL;
501: PetscFunctionReturn(PETSC_SUCCESS);
502: }
504: /* we do not free the column arrays since their entries are owned by the ISs in color->isa */
505: for (i = 0; i < color->ncolors; i++) PetscCall(ISDestroy(&color->isa[i]));
506: PetscCall(PetscFree(color->isa));
507: PetscCall(PetscFree2(color->ncolumns, color->columns));
508: PetscCall(PetscFree(color->nrows));
509: if (color->htype[0] == 'w') {
510: PetscCall(PetscFree(color->matentry2));
511: } else {
512: PetscCall(PetscFree(color->matentry));
513: }
514: PetscCall(PetscFree(color->dy));
515: if (color->vscale) PetscCall(VecDestroy(&color->vscale));
516: PetscCall(VecDestroy(&color->w1));
517: PetscCall(VecDestroy(&color->w2));
518: PetscCall(VecDestroy(&color->w3));
519: PetscCall(PetscHeaderDestroy(c));
520: PetscFunctionReturn(PETSC_SUCCESS);
521: }
523: /*@C
524: MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
525: that are currently being perturbed.
527: Not Collective
529: Input Parameter:
530: . coloring - coloring context created with `MatFDColoringCreate()`
532: Output Parameters:
533: + n - the number of local columns being perturbed
534: - cols - the column indices, in global numbering
536: Level: advanced
538: Note:
539: IF the matrix type is `MATBAIJ`, then the block column indices are returned
541: Fortran Note:
542: This routine has a different interface for Fortran
543: .vb
544: #include <petsc/finclude/petscmat.h>
545: use petscmat
546: PetscInt, pointer :: array(:)
547: PetscErrorCode ierr
548: MatFDColoring i
549: call MatFDColoringGetPerturbedColumnsF90(i,array,ierr)
550: use the entries of array ...
551: call MatFDColoringRestorePerturbedColumnsF90(i,array,ierr)
552: .ve
554: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringDestroy()`, `MatFDColoringView()`, `MatFDColoringApply()`
555: @*/
556: PetscErrorCode MatFDColoringGetPerturbedColumns(MatFDColoring coloring, PetscInt *n, const PetscInt *cols[])
557: {
558: PetscFunctionBegin;
559: if (coloring->currentcolor >= 0) {
560: *n = coloring->ncolumns[coloring->currentcolor];
561: *cols = coloring->columns[coloring->currentcolor];
562: } else {
563: *n = 0;
564: }
565: PetscFunctionReturn(PETSC_SUCCESS);
566: }
568: /*@
569: MatFDColoringApply - Given a matrix for which a `MatFDColoring` context
570: has been created, computes the Jacobian for a function via finite differences.
572: Collective
574: Input Parameters:
575: + mat - location to store Jacobian
576: . coloring - coloring context created with `MatFDColoringCreate()`
577: . x1 - location at which Jacobian is to be computed
578: - sctx - context required by function, if this is being used with the SNES solver then it is `SNES` object, otherwise it is null
580: Options Database Keys:
581: + -mat_fd_type - "wp" or "ds" (see `MATMFFD_WP` or `MATMFFD_DS`)
582: . -mat_fd_coloring_view - Activates basic viewing or coloring
583: . -mat_fd_coloring_view draw - Activates drawing of coloring
584: - -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info
586: Level: intermediate
588: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringDestroy()`, `MatFDColoringView()`, `MatFDColoringSetFunction()`, `MatFDColoringSetValues()`
589: @*/
590: PetscErrorCode MatFDColoringApply(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
591: {
592: PetscBool eq;
594: PetscFunctionBegin;
598: PetscCall(PetscObjectCompareId((PetscObject)J, coloring->matid, &eq));
599: PetscCheck(eq, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_WRONG, "Matrix used with MatFDColoringApply() must be that used with MatFDColoringCreate()");
600: PetscCheck(coloring->f, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_WRONGSTATE, "Must call MatFDColoringSetFunction()");
601: PetscCheck(coloring->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call MatFDColoringSetUp()");
603: PetscCall(MatSetUnfactored(J));
604: PetscCall(PetscLogEventBegin(MAT_FDColoringApply, coloring, J, x1, 0));
605: PetscUseTypeMethod(J, fdcoloringapply, coloring, x1, sctx);
606: PetscCall(PetscLogEventEnd(MAT_FDColoringApply, coloring, J, x1, 0));
607: if (!coloring->viewed) {
608: PetscCall(MatFDColoringViewFromOptions(coloring, NULL, "-mat_fd_coloring_view"));
609: coloring->viewed = PETSC_TRUE;
610: }
611: PetscFunctionReturn(PETSC_SUCCESS);
612: }