Actual source code: fdmatrix.c

  1: /*
  2:    This is where the abstract matrix operations are defined that are
  3:   used for finite difference computations of Jacobians using coloring.
  4: */

  6: #include <petsc/private/matimpl.h>
  7: #include <petsc/private/isimpl.h>

  9: /*@
 10:   MatFDColoringSetF - Cache the current function value used by the finite-difference coloring context to
 11:   avoid recomputing `F(x)` during a Jacobian evaluation.

 13:   Logically Collective

 15:   Input Parameters:
 16: + fd - the `MatFDColoring` context
 17: - F  - the current function value `F(x)`, or `NULL` to invalidate any cached value

 19:   Level: advanced

 21: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringApply()`
 22: @*/
 23: PetscErrorCode MatFDColoringSetF(MatFDColoring fd, Vec F)
 24: {
 25:   PetscFunctionBegin;
 26:   if (F) {
 27:     PetscCall(VecCopy(F, fd->w1));
 28:     fd->fset = PETSC_TRUE;
 29:   } else {
 30:     fd->fset = PETSC_FALSE;
 31:   }
 32:   PetscFunctionReturn(PETSC_SUCCESS);
 33: }

 35: #include <petscdraw.h>
 36: static PetscErrorCode MatFDColoringView_Draw_Zoom(PetscDraw draw, void *Aa)
 37: {
 38:   MatFDColoring fd = (MatFDColoring)Aa;
 39:   PetscMPIInt   i, j, nz;
 40:   PetscInt      row;
 41:   PetscReal     x, y;
 42:   MatEntry     *Jentry = fd->matentry;

 44:   PetscFunctionBegin;
 45:   /* loop over colors  */
 46:   nz = 0;
 47:   for (i = 0; i < fd->ncolors; i++) {
 48:     for (j = 0; j < fd->nrows[i]; j++) {
 49:       row = Jentry[nz].row;
 50:       y   = fd->M - row - fd->rstart;
 51:       x   = (PetscReal)Jentry[nz++].col;
 52:       PetscCall(PetscDrawRectangle(draw, x, y, x + 1, y + 1, i + 1, i + 1, i + 1, i + 1));
 53:     }
 54:   }
 55:   PetscFunctionReturn(PETSC_SUCCESS);
 56: }

 58: static PetscErrorCode MatFDColoringView_Draw(MatFDColoring fd, PetscViewer viewer)
 59: {
 60:   PetscBool isnull;
 61:   PetscDraw draw;
 62:   PetscReal xr, yr, xl, yl, h, w;

 64:   PetscFunctionBegin;
 65:   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
 66:   PetscCall(PetscDrawIsNull(draw, &isnull));
 67:   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);

 69:   xr = fd->N;
 70:   yr = fd->M;
 71:   h  = yr / 10.0;
 72:   w  = xr / 10.0;
 73:   xr += w;
 74:   yr += h;
 75:   xl = -w;
 76:   yl = -h;
 77:   PetscCall(PetscDrawSetCoordinates(draw, xl, yl, xr, yr));
 78:   PetscCall(PetscObjectCompose((PetscObject)fd, "Zoomviewer", (PetscObject)viewer));
 79:   PetscCall(PetscDrawZoom(draw, MatFDColoringView_Draw_Zoom, fd));
 80:   PetscCall(PetscObjectCompose((PetscObject)fd, "Zoomviewer", NULL));
 81:   PetscCall(PetscDrawSave(draw));
 82:   PetscFunctionReturn(PETSC_SUCCESS);
 83: }

 85: /*@
 86:   MatFDColoringView - Views a finite difference coloring context.

 88:   Collective

 90:   Input Parameters:
 91: + c      - the coloring context
 92: - viewer - visualization context

 94:   Level: intermediate

 96:   Notes:
 97:   The available visualization contexts include
 98: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
 99: .     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
100:   output where only the first processor opens
101:   the file.  All other processors send their
102:   data to the first processor to print.
103: -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure

105:   Since PETSc uses only a small number of basic colors (currently 33), if the coloring
106:   involves more than 33 then some seemingly identical colors are displayed making it look
107:   like an illegal coloring. This is just a graphical artifact.

109: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`
110: @*/
111: PetscErrorCode MatFDColoringView(MatFDColoring c, PetscViewer viewer)
112: {
113:   PetscBool         isdraw, isascii;
114:   PetscViewerFormat format;

116:   PetscFunctionBegin;
118:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c), &viewer));
120:   PetscCheckSameComm(c, 1, viewer, 2);

122:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
123:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
124:   if (isdraw) {
125:     PetscCall(MatFDColoringView_Draw(c, viewer));
126:   } else if (isascii) {
127:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)c, viewer));
128:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Error tolerance=%g\n", (double)c->error_rel));
129:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Umin=%g\n", (double)c->umin));
130:     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of colors=%" PetscInt_FMT "\n", c->ncolors));

132:     PetscCall(PetscViewerGetFormat(viewer, &format));
133:     if (format != PETSC_VIEWER_ASCII_INFO) {
134:       PetscInt row, col, nz;
135:       nz = 0;
136:       for (PetscInt i = 0; i < c->ncolors; i++) {
137:         PetscCall(PetscViewerASCIIPrintf(viewer, "  Information for color %" PetscInt_FMT "\n", i));
138:         PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of columns %" PetscInt_FMT "\n", c->ncolumns[i]));
139:         for (PetscInt j = 0; j < c->ncolumns[i]; j++) PetscCall(PetscViewerASCIIPrintf(viewer, "      %" PetscInt_FMT "\n", c->columns[i][j]));
140:         PetscCall(PetscViewerASCIIPrintf(viewer, "    Number of rows %" PetscInt_FMT "\n", c->nrows[i]));
141:         if (c->matentry) {
142:           for (PetscInt j = 0; j < c->nrows[i]; j++) {
143:             row = c->matentry[nz].row;
144:             col = c->matentry[nz++].col;
145:             PetscCall(PetscViewerASCIIPrintf(viewer, "      %" PetscInt_FMT " %" PetscInt_FMT " \n", row, col));
146:           }
147:         }
148:       }
149:     }
150:     PetscCall(PetscViewerFlush(viewer));
151:   }
152:   PetscFunctionReturn(PETSC_SUCCESS);
153: }

155: /*@
156:   MatFDColoringSetParameters - Sets the parameters for the approximation of
157:   a sparse Jacobian matrix using finite differences and matrix coloring

159:   Logically Collective

161:   Input Parameters:
162: + matfd - the coloring context
163: . error - relative error
164: - umin  - minimum allowable u-value magnitude

166:   Level: advanced

168:   Note:
169:   The Jacobian is estimated with the differencing approximation
170: .vb
171:        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
172:        htype = 'ds':
173:          h = error_rel*u[i]                 if  abs(u[i]) > umin
174:            = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
175:          dx_{i} = (0, ... 1, .... 0)

177:        htype = 'wp':
178:          h = error_rel * sqrt(1 + ||u||)
179: .ve

181: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringSetFromOptions()`
182: @*/
183: PetscErrorCode MatFDColoringSetParameters(MatFDColoring matfd, PetscReal error, PetscReal umin)
184: {
185:   PetscFunctionBegin;
189:   if (error != (PetscReal)PETSC_DEFAULT) matfd->error_rel = error;
190:   if (umin != (PetscReal)PETSC_DEFAULT) matfd->umin = umin;
191:   PetscFunctionReturn(PETSC_SUCCESS);
192: }

194: /*@
195:   MatFDColoringSetBlockSize - Sets block size for efficient inserting entries of Jacobian matrix.

197:   Logically Collective

199:   Input Parameters:
200: + matfd - the coloring context
201: . brows - number of rows in the block
202: - bcols - number of columns in the block

204:   Level: intermediate

206: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringSetFromOptions()`
207: @*/
208: PetscErrorCode MatFDColoringSetBlockSize(MatFDColoring matfd, PetscInt brows, PetscInt bcols)
209: {
210:   PetscFunctionBegin;
214:   if (brows != PETSC_DEFAULT) matfd->brows = brows;
215:   if (bcols != PETSC_DEFAULT) matfd->bcols = bcols;
216:   PetscFunctionReturn(PETSC_SUCCESS);
217: }

219: /*@
220:   MatFDColoringSetUp - Sets up the internal data structures of matrix coloring context for the later use.

222:   Collective

224:   Input Parameters:
225: + mat        - the matrix containing the nonzero structure of the Jacobian
226: . iscoloring - the coloring of the matrix; usually obtained with `MatGetColoring()` or `DMCreateColoring()`
227: - color      - the matrix coloring context

229:   Level: beginner

231:   Notes:
232:   When the coloring type is `IS_COLORING_LOCAL` the coloring is in the local ordering of the unknowns.

234: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringDestroy()`
235: @*/
236: PetscErrorCode MatFDColoringSetUp(Mat mat, ISColoring iscoloring, MatFDColoring color)
237: {
238:   PetscBool eq;

240:   PetscFunctionBegin;
243:   if (color->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
244:   PetscCall(PetscObjectCompareId((PetscObject)mat, color->matid, &eq));
245:   PetscCheck(eq, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix used with MatFDColoringSetUp() must be that used with MatFDColoringCreate()");

247:   PetscCall(PetscLogEventBegin(MAT_FDColoringSetUp, mat, 0, 0, 0));
248:   PetscUseTypeMethod(mat, fdcoloringsetup, iscoloring, color);

250:   color->setupcalled = PETSC_TRUE;
251:   PetscCall(PetscLogEventEnd(MAT_FDColoringSetUp, mat, 0, 0, 0));
252:   PetscFunctionReturn(PETSC_SUCCESS);
253: }

255: /*@C
256:   MatFDColoringGetFunction - Gets the function to use for computing the Jacobian.

258:   Not Collective

260:   Input Parameter:
261: . matfd - the coloring context

263:   Output Parameters:
264: + f    - the function, see `MatFDColoringFn` for the calling sequence
265: - fctx - the optional user-defined function context

267:   Level: intermediate

269: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringSetFunction()`, `MatFDColoringSetFromOptions()`, `MatFDColoringFn`
270: @*/
271: PetscErrorCode MatFDColoringGetFunction(MatFDColoring matfd, MatFDColoringFn **f, void **fctx)
272: {
273:   PetscFunctionBegin;
275:   if (f) *f = matfd->f;
276:   if (fctx) *fctx = matfd->fctx;
277:   PetscFunctionReturn(PETSC_SUCCESS);
278: }

280: /*@C
281:   MatFDColoringSetFunction - Sets the function to use for computing the Jacobian.

283:   Logically Collective

285:   Input Parameters:
286: + matfd - the coloring context
287: . f     - the function, see `MatFDColoringFn` for the calling sequence
288: - fctx  - the optional user-defined function context

290:   Level: advanced

292:   Note:
293:   This function is usually used automatically by `SNES` (when one uses `SNESSetJacobian()` with the argument
294:   `SNESComputeJacobianDefaultColor()`) and only needs to be used by someone computing a matrix via coloring directly by
295:   calling `MatFDColoringApply()`

297:   Fortran Note:
298:   In Fortran you must call `MatFDColoringSetFunction()` for a coloring object to
299:   be used without `SNES` or within the `SNES` solvers.

301: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringGetFunction()`, `MatFDColoringSetFromOptions()`, `MatFDColoringFn`
302: @*/
303: PetscErrorCode MatFDColoringSetFunction(MatFDColoring matfd, MatFDColoringFn *f, void *fctx)
304: {
305:   PetscFunctionBegin;
307:   matfd->f    = f;
308:   matfd->fctx = fctx;
309:   PetscFunctionReturn(PETSC_SUCCESS);
310: }

312: /*@
313:   MatFDColoringSetFromOptions - Sets coloring finite difference parameters from
314:   the options database.

316:   Collective

318:   The Jacobian, F'(u), is estimated with the differencing approximation
319: .vb
320:        F'(u)_{:,i} = [F(u+h*dx_{i}) - F(u)]/h where
321:        h = error_rel*u[i]                 if  abs(u[i]) > umin
322:          = +/- error_rel*umin             otherwise, with +/- determined by the sign of u[i]
323:        dx_{i} = (0, ... 1, .... 0)
324: .ve

326:   Input Parameter:
327: . matfd - the coloring context

329:   Options Database Keys:
330: + -mat_fd_coloring_err err           - Sets err (square root of relative error in the function)
331: . -mat_fd_coloring_umin umin         - Sets umin, the minimum allowable u-value magnitude
332: . -mat_fd_type (wp|ds)               - See `MATMFFD_WP` and `MATMFFD_DS`
333: . -mat_fd_coloring_view              - Activates basic viewing
334: . -mat_fd_coloring_view ::ascii_info - Activates viewing info
335: - -mat_fd_coloring_view draw         - Activates drawing

337:   Level: intermediate

339: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringView()`, `MatFDColoringSetParameters()`
340: @*/
341: PetscErrorCode MatFDColoringSetFromOptions(MatFDColoring matfd)
342: {
343:   PetscBool flg;
344:   char      value[3];

346:   PetscFunctionBegin;

349:   PetscObjectOptionsBegin((PetscObject)matfd);
350:   PetscCall(PetscOptionsReal("-mat_fd_coloring_err", "Square root of relative error in function", "MatFDColoringSetParameters", matfd->error_rel, &matfd->error_rel, NULL));
351:   PetscCall(PetscOptionsReal("-mat_fd_coloring_umin", "Minimum allowable u magnitude", "MatFDColoringSetParameters", matfd->umin, &matfd->umin, NULL));
352:   PetscCall(PetscOptionsString("-mat_fd_type", "Algorithm to compute h, wp or ds", "MatFDColoringCreate", matfd->htype, value, sizeof(value), &flg));
353:   if (flg) {
354:     if (value[0] == 'w' && value[1] == 'p') matfd->htype = "wp";
355:     else if (value[0] == 'd' && value[1] == 's') matfd->htype = "ds";
356:     else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown finite differencing type %s", value);
357:   }
358:   PetscCall(PetscOptionsInt("-mat_fd_coloring_brows", "Number of block rows", "MatFDColoringSetBlockSize", matfd->brows, &matfd->brows, NULL));
359:   PetscCall(PetscOptionsInt("-mat_fd_coloring_bcols", "Number of block columns", "MatFDColoringSetBlockSize", matfd->bcols, &matfd->bcols, &flg));
360:   if (flg && matfd->bcols > matfd->ncolors) {
361:     /* input bcols cannot be > matfd->ncolors, thus set it as ncolors */
362:     matfd->bcols = matfd->ncolors;
363:   }

365:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
366:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)matfd, PetscOptionsObject));
367:   PetscOptionsEnd();
368:   PetscFunctionReturn(PETSC_SUCCESS);
369: }

371: /*@
372:   MatFDColoringSetType - Sets the approach for computing the finite difference parameter

374:   Collective

376:   Input Parameters:
377: + matfd - the coloring context
378: - type  - either `MATMFFD_WP` or `MATMFFD_DS`

380:   Options Database Key:
381: . -mat_fd_type - "wp" or "ds"

383:   Level: intermediate

385:   Note:
386:   It is goofy that the argument type is `MatMFFDType` since the `MatFDColoring` actually computes the matrix entries
387:   but the process of computing the entries is the same as with the `MATMFFD` operation so we should reuse the names instead of
388:   introducing another one.

390: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringView()`, `MatFDColoringSetParameters()`
391: @*/
392: PetscErrorCode MatFDColoringSetType(MatFDColoring matfd, MatMFFDType type)
393: {
394:   PetscFunctionBegin;
396:   /*
397:      It is goofy to handle the strings this way but currently there is no code to free a dynamically created matfd->htype
398:      and this function is being provided as patch for a release so it shouldn't change the implementation
399:   */
400:   if (type[0] == 'w' && type[1] == 'p') matfd->htype = "wp";
401:   else if (type[0] == 'd' && type[1] == 's') matfd->htype = "ds";
402:   else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unknown finite differencing type %s", type);
403:   PetscCall(PetscObjectChangeTypeName((PetscObject)matfd, type));
404:   PetscFunctionReturn(PETSC_SUCCESS);
405: }

407: static PetscErrorCode MatFDColoringViewFromOptions(MatFDColoring fd, const char prefix[], const char optionname[])
408: {
409:   PetscBool         flg;
410:   PetscViewer       viewer;
411:   PetscViewerFormat format;

413:   PetscFunctionBegin;
414:   if (prefix) {
415:     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)fd), ((PetscObject)fd)->options, prefix, optionname, &viewer, &format, &flg));
416:   } else {
417:     PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)fd), ((PetscObject)fd)->options, ((PetscObject)fd)->prefix, optionname, &viewer, &format, &flg));
418:   }
419:   if (flg) {
420:     PetscCall(PetscViewerPushFormat(viewer, format));
421:     PetscCall(MatFDColoringView(fd, viewer));
422:     PetscCall(PetscViewerPopFormat(viewer));
423:     PetscCall(PetscViewerDestroy(&viewer));
424:   }
425:   PetscFunctionReturn(PETSC_SUCCESS);
426: }

428: /*@
429:   MatFDColoringCreate - Creates a matrix coloring context for finite difference
430:   computation of Jacobians.

432:   Collective

434:   Input Parameters:
435: + mat        - the matrix containing the nonzero structure of the Jacobian
436: - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`

438:   Output Parameter:
439: . color - the new coloring context

441:   Level: intermediate

443: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringDestroy()`, `SNESComputeJacobianDefaultColor()`, `ISColoringCreate()`,
444:           `MatFDColoringSetFunction()`, `MatFDColoringSetFromOptions()`, `MatFDColoringApply()`,
445:           `MatFDColoringView()`, `MatFDColoringSetParameters()`, `MatColoringCreate()`, `DMCreateColoring()`, `MatFDColoringSetValues()`
446: @*/
447: PetscErrorCode MatFDColoringCreate(Mat mat, ISColoring iscoloring, MatFDColoring *color)
448: {
449:   MatFDColoring c;
450:   MPI_Comm      comm;
451:   PetscInt      M, N;

453:   PetscFunctionBegin;
455:   PetscAssertPointer(color, 3);
456:   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be assembled by calls to MatAssemblyBegin/End();");
457:   PetscCall(PetscLogEventBegin(MAT_FDColoringCreate, mat, 0, 0, 0));
458:   PetscCall(MatGetSize(mat, &M, &N));
459:   PetscCheck(M == N, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Only for square matrices");
460:   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
461:   PetscCall(PetscHeaderCreate(c, MAT_FDCOLORING_CLASSID, "MatFDColoring", "Jacobian computation via finite differences with coloring", "Mat", comm, MatFDColoringDestroy, MatFDColoringView));

463:   c->ctype = iscoloring->ctype;
464:   PetscCall(PetscObjectGetId((PetscObject)mat, &c->matid));

466:   PetscUseTypeMethod(mat, fdcoloringcreate, iscoloring, c);

468:   PetscCall(MatCreateVecs(mat, NULL, &c->w1));
469:   /* Vec is used intensively in particular piece of scalar CPU code; won't benefit from bouncing back and forth to the GPU */
470:   PetscCall(VecBindToCPU(c->w1, PETSC_TRUE));
471:   PetscCall(VecDuplicate(c->w1, &c->w2));
472:   /* Vec is used intensively in particular piece of scalar CPU code; won't benefit from bouncing back and forth to the GPU */
473:   PetscCall(VecBindToCPU(c->w2, PETSC_TRUE));

475:   c->error_rel    = PETSC_SQRT_MACHINE_EPSILON;
476:   c->umin         = 100.0 * PETSC_SQRT_MACHINE_EPSILON;
477:   c->currentcolor = -1;
478:   c->htype        = "wp";
479:   c->fset         = PETSC_FALSE;
480:   c->setupcalled  = PETSC_FALSE;

482:   *color = c;
483:   PetscCall(PetscObjectCompose((PetscObject)mat, "SNESMatFDColoring", (PetscObject)c));
484:   PetscCall(PetscLogEventEnd(MAT_FDColoringCreate, mat, 0, 0, 0));
485:   PetscFunctionReturn(PETSC_SUCCESS);
486: }

488: /*@
489:   MatFDColoringDestroy - Destroys a matrix coloring context that was created
490:   via `MatFDColoringCreate()`.

492:   Collective

494:   Input Parameter:
495: . c - coloring context

497:   Level: intermediate

499: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`
500: @*/
501: PetscErrorCode MatFDColoringDestroy(MatFDColoring *c)
502: {
503:   MatFDColoring color = *c;

505:   PetscFunctionBegin;
506:   if (!*c) PetscFunctionReturn(PETSC_SUCCESS);
507:   if (--((PetscObject)color)->refct > 0) {
508:     *c = NULL;
509:     PetscFunctionReturn(PETSC_SUCCESS);
510:   }

512:   /* we do not free the column arrays since their entries are owned by the ISs in color->isa */
513:   for (PetscInt i = 0; i < color->ncolors; i++) PetscCall(ISDestroy(&color->isa[i]));
514:   PetscCall(PetscFree(color->isa));
515:   PetscCall(PetscFree2(color->ncolumns, color->columns));
516:   PetscCall(PetscFree(color->nrows));
517:   if (color->htype[0] == 'w') {
518:     PetscCall(PetscFree(color->matentry2));
519:   } else {
520:     PetscCall(PetscFree(color->matentry));
521:   }
522:   PetscCall(PetscFree(color->dy));
523:   PetscCall(VecDestroy(&color->vscale));
524:   PetscCall(VecDestroy(&color->w1));
525:   PetscCall(VecDestroy(&color->w2));
526:   PetscCall(VecDestroy(&color->w3));
527:   PetscCall(PetscHeaderDestroy(c));
528:   PetscFunctionReturn(PETSC_SUCCESS);
529: }

531: /*@C
532:   MatFDColoringGetPerturbedColumns - Returns the indices of the columns that
533:   that are currently being perturbed.

535:   Not Collective

537:   Input Parameter:
538: . coloring - coloring context created with `MatFDColoringCreate()`

540:   Output Parameters:
541: + n    - the number of local columns being perturbed
542: - cols - the column indices, in global numbering

544:   Level: advanced

546:   Note:
547:   IF the matrix type is `MATBAIJ`, then the block column indices are returned

549:   Fortran Note:
550: .vb
551:   PetscInt, pointer :: cols(:)
552: .ve
553:   Use `PETSC_NULL_INTEGER` if `n` is not needed

555: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringDestroy()`, `MatFDColoringView()`, `MatFDColoringApply()`
556: @*/
557: PetscErrorCode MatFDColoringGetPerturbedColumns(MatFDColoring coloring, PetscInt *n, const PetscInt *cols[])
558: {
559:   PetscFunctionBegin;
560:   if (coloring->currentcolor >= 0) {
561:     *n    = coloring->ncolumns[coloring->currentcolor];
562:     *cols = coloring->columns[coloring->currentcolor];
563:   } else {
564:     *n = 0;
565:   }
566:   PetscFunctionReturn(PETSC_SUCCESS);
567: }

569: /*@
570:   MatFDColoringApply - Given a matrix for which a `MatFDColoring` context
571:   has been created, computes the Jacobian for a function via finite differences.

573:   Collective

575:   Input Parameters:
576: + J        - matrix to store Jacobian entries into
577: . coloring - coloring context created with `MatFDColoringCreate()`
578: . x1       - location at which Jacobian is to be computed
579: - sctx     - context required by function, if this is being used with the `SNES` solver then it is `SNES` object, otherwise it is `NULL`

581:   Options Database Keys:
582: + -mat_fd_type                       - "wp" or "ds"  (see `MATMFFD_WP` or `MATMFFD_DS`)
583: . -mat_fd_coloring_view              - Activates basic viewing or coloring
584: . -mat_fd_coloring_view draw         - Activates drawing of coloring
585: - -mat_fd_coloring_view ::ascii_info - Activates viewing of coloring info

587:   Level: intermediate

589: .seealso: `Mat`, `MatFDColoring`, `MatFDColoringCreate()`, `MatFDColoringDestroy()`, `MatFDColoringView()`, `MatFDColoringSetFunction()`, `MatFDColoringSetValues()`
590: @*/
591: PetscErrorCode MatFDColoringApply(Mat J, MatFDColoring coloring, Vec x1, void *sctx)
592: {
593:   PetscBool eq;

595:   PetscFunctionBegin;
599:   PetscCall(PetscObjectCompareId((PetscObject)J, coloring->matid, &eq));
600:   PetscCheck(eq, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_WRONG, "Matrix used with MatFDColoringApply() must be that used with MatFDColoringCreate()");
601:   PetscCheck(coloring->f, PetscObjectComm((PetscObject)J), PETSC_ERR_ARG_WRONGSTATE, "Must call MatFDColoringSetFunction()");
602:   PetscCheck(coloring->setupcalled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Must call MatFDColoringSetUp()");

604:   PetscCall(MatSetUnfactored(J));
605:   PetscCall(PetscLogEventBegin(MAT_FDColoringApply, coloring, J, x1, 0));
606:   PetscUseTypeMethod(J, fdcoloringapply, coloring, x1, sctx);
607:   PetscCall(PetscLogEventEnd(MAT_FDColoringApply, coloring, J, x1, 0));
608:   if (!coloring->viewed) {
609:     PetscCall(MatFDColoringViewFromOptions(coloring, NULL, "-mat_fd_coloring_view"));
610:     coloring->viewed = PETSC_TRUE;
611:   }
612:   PetscFunctionReturn(PETSC_SUCCESS);
613: }