Actual source code: dmksp.c

  1: #include <petsc/private/dmimpl.h>
  2: #include <petsc/private/kspimpl.h>
  3: #include <petscdm.h>

  5: static PetscErrorCode DMKSPDestroy(DMKSP *kdm)
  6: {
  7:   PetscFunctionBegin;
  8:   if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
 10:   if (--((PetscObject)*kdm)->refct > 0) {
 11:     *kdm = NULL;
 12:     PetscFunctionReturn(PETSC_SUCCESS);
 13:   }
 14:   if ((*kdm)->ops->destroy) PetscCall(((*kdm)->ops->destroy)(kdm));
 15:   PetscCall(PetscHeaderDestroy(kdm));
 16:   PetscFunctionReturn(PETSC_SUCCESS);
 17: }

 19: static PetscErrorCode DMKSPCreate(MPI_Comm comm, DMKSP *kdm)
 20: {
 21:   PetscFunctionBegin;
 22:   PetscCall(KSPInitializePackage());
 23:   PetscCall(PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL));
 24:   PetscFunctionReturn(PETSC_SUCCESS);
 25: }

 27: /* Attaches the DMKSP to the coarse level.
 28:  * Under what conditions should we copy versus duplicate?
 29:  */
 30: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm, DM dmc, void *ctx)
 31: {
 32:   PetscFunctionBegin;
 33:   PetscCall(DMCopyDMKSP(dm, dmc));
 34:   PetscFunctionReturn(PETSC_SUCCESS);
 35: }

 37: /* Attaches the DMKSP to the coarse level.
 38:  * Under what conditions should we copy versus duplicate?
 39:  */
 40: static PetscErrorCode DMRefineHook_DMKSP(DM dm, DM dmc, void *ctx)
 41: {
 42:   PetscFunctionBegin;
 43:   PetscCall(DMCopyDMKSP(dm, dmc));
 44:   PetscFunctionReturn(PETSC_SUCCESS);
 45: }

 47: /*
 48:   DMKSPCopy - copies the information in a `DMKSP` to another `DMKSP`

 50:   Not Collective

 52:   Input Parameters:
 53: + kdm  - Original `DMKSP`
 54: - nkdm - `DMKSP` to receive the data, created with `DMKSPCreate()`

 56:   Level: developer

 58: .seealso: [](ch_ksp), `DMKSP`, `DMKSPCreate()`, `DMKSPDestroy()`
 59: */
 60: static PetscErrorCode DMKSPCopy(DMKSP kdm, DMKSP nkdm)
 61: {
 62:   PetscFunctionBegin;
 65:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
 66:   nkdm->ops->computerhs          = kdm->ops->computerhs;
 67:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
 68:   nkdm->ops->destroy             = kdm->ops->destroy;
 69:   nkdm->ops->duplicate           = kdm->ops->duplicate;

 71:   nkdm->operatorsctx    = kdm->operatorsctx;
 72:   nkdm->rhsctx          = kdm->rhsctx;
 73:   nkdm->initialguessctx = kdm->initialguessctx;
 74:   nkdm->data            = kdm->data;
 75:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */

 77:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 78:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 79:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

 81:   /* implementation specific copy hooks */
 82:   PetscTryTypeMethod(kdm, duplicate, nkdm);
 83:   PetscFunctionReturn(PETSC_SUCCESS);
 84: }

 86: /*@C
 87:   DMGetDMKSP - get the read-only private `DMKSP` context from a `DM`

 89:   Logically Collective

 91:   Input Parameter:
 92: . dm - `DM` used with a `KSP`

 94:   Output Parameter:
 95: . kspdm - private `DMKSP` context

 97:   Level: developer

 99:   Note:
100:   Use `DMGetDMKSPWrite()` if write access is needed. The DMKSPSetXXX API should be used wherever possible.

102: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSPWrite()`
103: @*/
104: PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
105: {
106:   PetscFunctionBegin;
108:   *kspdm = (DMKSP)dm->dmksp;
109:   if (!*kspdm) {
110:     PetscCall(PetscInfo(dm, "Creating new DMKSP\n"));
111:     PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), kspdm));
112:     dm->dmksp            = (PetscObject)*kspdm;
113:     (*kspdm)->originaldm = dm;
114:     PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMKSP, NULL, NULL));
115:     PetscCall(DMRefineHookAdd(dm, DMRefineHook_DMKSP, NULL, NULL));
116:   }
117:   PetscFunctionReturn(PETSC_SUCCESS);
118: }

120: /*@C
121:   DMGetDMKSPWrite - get write access to private `DMKSP` context from a `DM`

123:   Logically Collective

125:   Input Parameter:
126: . dm - `DM` used with a `KSP`

128:   Output Parameter:
129: . kspdm - private `DMKSP` context

131:   Level: developer

133: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`
134: @*/
135: PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
136: {
137:   DMKSP kdm;

139:   PetscFunctionBegin;
141:   PetscCall(DMGetDMKSP(dm, &kdm));
142:   PetscCheck(kdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMKSP has a NULL originaldm");
143:   if (kdm->originaldm != dm) { /* Copy on write */
144:     DMKSP oldkdm = kdm;
145:     PetscCall(PetscInfo(dm, "Copying DMKSP due to write\n"));
146:     PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), &kdm));
147:     PetscCall(DMKSPCopy(oldkdm, kdm));
148:     PetscCall(DMKSPDestroy((DMKSP *)&dm->dmksp));
149:     dm->dmksp       = (PetscObject)kdm;
150:     kdm->originaldm = dm;
151:   }
152:   *kspdm = kdm;
153:   PetscFunctionReturn(PETSC_SUCCESS);
154: }

156: /*@C
157:   DMCopyDMKSP - copies a `DM` `DMKSP` context to a new `DM`

159:   Logically Collective

161:   Input Parameters:
162: + dmsrc  - `DM` to obtain context from
163: - dmdest - `DM` to add context to

165:   Level: developer

167:   Note:
168:   The context is copied by reference. This function does not ensure that a context exists.

170: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`, `KSPSetDM()`
171: @*/
172: PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
173: {
174:   PetscFunctionBegin;
177:   PetscCall(DMKSPDestroy((DMKSP *)&dmdest->dmksp));
178:   dmdest->dmksp = dmsrc->dmksp;
179:   PetscCall(PetscObjectReference(dmdest->dmksp));
180:   PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMKSP, NULL, NULL));
181:   PetscCall(DMRefineHookAdd(dmdest, DMRefineHook_DMKSP, NULL, NULL));
182:   PetscFunctionReturn(PETSC_SUCCESS);
183: }

185: /*@C
186:   DMKSPSetComputeOperators - set `KSP` matrix evaluation function

188:   Not Collective

190:   Input Parameters:
191: + dm   - `DM` to be used with `KSP`
192: . func - matrix evaluation function,  for calling sequence see `KSPComputeOperatorsFn`
193: - ctx  - context for matrix evaluation

195:   Level: developer

197:   Note:
198:   `KSPSetComputeOperators()` is normally used, but it calls this function internally because the user context is actually
199:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
200:   not.

202:   Developer Note:
203:   If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.

205: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`, `KSPComputeOperatorsFn`
206: @*/
207: PetscErrorCode DMKSPSetComputeOperators(DM dm, KSPComputeOperatorsFn *func, void *ctx)
208: {
209:   DMKSP kdm;

211:   PetscFunctionBegin;
213:   PetscCall(DMGetDMKSPWrite(dm, &kdm));
214:   if (func) kdm->ops->computeoperators = func;
215:   if (ctx) kdm->operatorsctx = ctx;
216:   PetscFunctionReturn(PETSC_SUCCESS);
217: }

219: /*@C
220:   DMKSPGetComputeOperators - get `KSP` matrix evaluation function

222:   Not Collective

224:   Input Parameter:
225: . dm - `DM` used with a `KSP`

227:   Output Parameters:
228: + func - matrix evaluation function,  for calling sequence see `KSPComputeOperatorsFn`
229: - ctx  - context for matrix evaluation

231:   Level: developer

233: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`, `KSPComputeOperatorsFn`
234: @*/
235: PetscErrorCode DMKSPGetComputeOperators(DM dm, KSPComputeOperatorsFn **func, void *ctx)
236: {
237:   DMKSP kdm;

239:   PetscFunctionBegin;
241:   PetscCall(DMGetDMKSP(dm, &kdm));
242:   if (func) *func = kdm->ops->computeoperators;
243:   if (ctx) *(void **)ctx = kdm->operatorsctx;
244:   PetscFunctionReturn(PETSC_SUCCESS);
245: }

247: /*@C
248:   DMKSPSetComputeRHS - set `KSP` right hand side evaluation function

250:   Not Collective

252:   Input Parameters:
253: + dm   - `DM` used with a `KSP`
254: . func - right hand side evaluation function,  for calling sequence see `KSPComputeRHSFn`
255: - ctx  - context for right hand side evaluation

257:   Level: developer

259:   Note:
260:   `KSPSetComputeRHS()` is normally used, but it calls this function internally because the user context is actually
261:   associated with the `DM`.  This makes the interface consistent regardless of whether the user interacts with a `DM` or
262:   not.

264:   Developer Note:
265:   If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.

267: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
268: @*/
269: PetscErrorCode DMKSPSetComputeRHS(DM dm, KSPComputeRHSFn *func, void *ctx)
270: {
271:   DMKSP kdm;

273:   PetscFunctionBegin;
275:   PetscCall(DMGetDMKSPWrite(dm, &kdm));
276:   if (func) kdm->ops->computerhs = func;
277:   if (ctx) kdm->rhsctx = ctx;
278:   PetscFunctionReturn(PETSC_SUCCESS);
279: }

281: /*@C
282:   DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function

284:   Not Collective

286:   Input Parameters:
287: + dm   - `DM` to be used with `KSP`
288: . func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
289: - ctx  - context for right hand side evaluation

291:   Level: developer

293:   Note:
294:   `KSPSetComputeInitialGuess()` is normally used, but it calls this function internally because the user context is actually
295:   associated with the `DM`.

297: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`, `KSPComputeInitialGuessFn`
298: @*/
299: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn *func, void *ctx)
300: {
301:   DMKSP kdm;

303:   PetscFunctionBegin;
305:   PetscCall(DMGetDMKSPWrite(dm, &kdm));
306:   if (func) kdm->ops->computeinitialguess = func;
307:   if (ctx) kdm->initialguessctx = ctx;
308:   PetscFunctionReturn(PETSC_SUCCESS);
309: }

311: /*@C
312:   DMKSPGetComputeRHS - get `KSP` right hand side evaluation function

314:   Not Collective

316:   Input Parameter:
317: . dm - `DM` to be used with `KSP`

319:   Output Parameters:
320: + func - right hand side evaluation function,  for calling sequence see `KSPComputeRHSFn`
321: - ctx  - context for right hand side evaluation

323:   Level: advanced

325: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeRHSFn`
326: @*/
327: PetscErrorCode DMKSPGetComputeRHS(DM dm, KSPComputeRHSFn **func, void *ctx)
328: {
329:   DMKSP kdm;

331:   PetscFunctionBegin;
333:   PetscCall(DMGetDMKSP(dm, &kdm));
334:   if (func) *func = kdm->ops->computerhs;
335:   if (ctx) *(void **)ctx = kdm->rhsctx;
336:   PetscFunctionReturn(PETSC_SUCCESS);
337: }

339: /*@C
340:   DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function

342:   Not Collective

344:   Input Parameter:
345: . dm - `DM` used with a `KSP`

347:   Output Parameters:
348: + func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
349: - ctx  - context for right hand side evaluation

351:   Level: advanced

353: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeInitialGuessFn`
354: @*/
355: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn **func, void *ctx)
356: {
357:   DMKSP kdm;

359:   PetscFunctionBegin;
361:   PetscCall(DMGetDMKSP(dm, &kdm));
362:   if (func) *func = kdm->ops->computeinitialguess;
363:   if (ctx) *(void **)ctx = kdm->initialguessctx;
364:   PetscFunctionReturn(PETSC_SUCCESS);
365: }