Skip to main content
`Ctrl`+`K`

# DMKSP

Object held by a `DM` that contains all the callback functions and their contexts needed by a `KSP`

## Synopsis

    struct _p_DMKSP {
      PETSCHEADER(struct _DMKSPOps);
      void *operatorsctx;
      void *rhsctx;
      void *initialguessctx;
      void *data;

      /* See developer note for `DMKSP` above */
      DM originaldm;

      void (*fortran_func_pointers[3])(void); /* Store our own function pointers so they are associated with the DMKSP instead of the DM */
    };

## Notes

Users provides callback functions and their contexts to `KSP` using, for example, `KSPSetComputeRHS()`. These values are stored in a `DMKSP` that is contained in the `DM` associated with the `KSP`. If no `DM` was provided by the user with `KSPSetDM()` it is automatically created by `KSPGetDM()` with `DMShellCreate()`.

Users very rarely need to worked directly with the `DMKSP` object, rather they work with the `KSP` and the `DM` they created

Multiple `DM` can share a single `DMKSP`, often each `DM` is associated with a grid refinement level. `DMGetDMKSP()` returns the `DMKSP` associated with a `DM`. `DMGetDMKSPWrite()` returns a unique `DMKSP` that is only associated with the current `DM`, making a copy of the shared `DMKSP` if needed (copy-on-write).

## Developer Notes

It is rather subtle why `DMKSP`, `DMSNES`, and `DMTS` are needed instead of simply storing the user callback functions and contexts in `DM` or `KSP`, `SNES`, or `TS`. It is to support composable solvers such as geometric multigrid. We want, by default, the same callback functions and contexts for all the levels in the computation, but we need to also support different callbacks and contexts on each level. The copy-on-write approach of `DMGetDMKSPWrite()` makes this possible.

The `originaldm` inside the `DMKSP` is NOT reference counted (to prevent a reference count loop between a `DM` and a `DMKSP`). The `DM` on which this context was first created is cached here to implement one-way copy-on-write. When `DMGetDMKSPWrite()` sees a request using a different `DM`, it makes a copy of the `TSDM`. Thus, if a user only interacts directly with one level, e.g., using `TSSetIFunction()`, then coarse levels of a multilevel item integrator are built, then the user changes the routine with another call to `TSSetIFunction()`, it automatically propagates to all the levels. If instead, they get out a specific level and set the function on that level, subsequent changes to the original level will no longer propagate to that level.

## See Also

TS: Scalable ODE and DAE Solvers, `KSP`, `KSPCreate()`, `DM`, `DMGetDMKSPWrite()`, `DMGetDMKSP()`, `DMSNES`, `DMTS`, `DMKSPSetComputeOperators()`, `DMKSPGetComputeOperators()`, `DMKSPSetComputeRHS()`, `DMKSPSetComputeInitialGuess()`

## Level

developer

## Location

include/petsc/private/kspimpl.h

Index of all KSP routines
Table of Contents for all manual pages
Index of all manual pages