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:   if (!*kdm) return 0;
  9:   if (--((PetscObject)(*kdm))->refct > 0) {
 10:     *kdm = NULL;
 11:     return 0;
 12:   }
 13:   if ((*kdm)->ops->destroy) ((*kdm)->ops->destroy)(kdm);
 14:   PetscHeaderDestroy(kdm);
 15:   return 0;
 16: }

 18: static PetscErrorCode DMKSPCreate(MPI_Comm comm, DMKSP *kdm)
 19: {
 20:   KSPInitializePackage();
 21:   PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
 22:   return 0;
 23: }

 25: /* Attaches the DMKSP to the coarse level.
 26:  * Under what conditions should we copy versus duplicate?
 27:  */
 28: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm, DM dmc, void *ctx)
 29: {
 30:   DMCopyDMKSP(dm, dmc);
 31:   return 0;
 32: }

 34: /* Attaches the DMKSP to the coarse level.
 35:  * Under what conditions should we copy versus duplicate?
 36:  */
 37: static PetscErrorCode DMRefineHook_DMKSP(DM dm, DM dmc, void *ctx)
 38: {
 39:   DMCopyDMKSP(dm, dmc);
 40:   return 0;
 41: }

 43: /*@C
 44:    DMKSPCopy - copies the information in a `DMKSP` to another `DMKSP`

 46:    Not Collective

 48:    Input Parameters:
 49: +  kdm - Original `DMKSP`
 50: -  nkdm - `DMKSP` to receive the data, created with `DMKSPCreate()`

 52:    Level: developer

 54: .seealso: [](chapter_ksp), `DMKSPCreate()`, `DMKSPDestroy()`
 55: @*/
 56: PetscErrorCode DMKSPCopy(DMKSP kdm, DMKSP nkdm)
 57: {
 60:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
 61:   nkdm->ops->computerhs          = kdm->ops->computerhs;
 62:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
 63:   nkdm->ops->destroy             = kdm->ops->destroy;
 64:   nkdm->ops->duplicate           = kdm->ops->duplicate;

 66:   nkdm->operatorsctx    = kdm->operatorsctx;
 67:   nkdm->rhsctx          = kdm->rhsctx;
 68:   nkdm->initialguessctx = kdm->initialguessctx;
 69:   nkdm->data            = kdm->data;
 70:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */

 72:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 73:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 74:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

 76:   /* implementation specific copy hooks */
 77:   PetscTryTypeMethod(kdm, duplicate, nkdm);
 78:   return 0;
 79: }

 81: /*@C
 82:    DMGetDMKSP - get read-only private `DMKSP` context from a `DM`

 84:    Logically Collective

 86:    Input Parameter:
 87: .  dm - `DM` used with a `KSP`

 89:    Output Parameter:
 90: .  snesdm - private `DMKSP` context

 92:    Level: developer

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

 97: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSPWrite()`
 98: @*/
 99: PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
100: {
102:   *kspdm = (DMKSP)dm->dmksp;
103:   if (!*kspdm) {
104:     PetscInfo(dm, "Creating new DMKSP\n");
105:     DMKSPCreate(PetscObjectComm((PetscObject)dm), kspdm);
106:     dm->dmksp            = (PetscObject)*kspdm;
107:     (*kspdm)->originaldm = dm;
108:     DMCoarsenHookAdd(dm, DMCoarsenHook_DMKSP, NULL, NULL);
109:     DMRefineHookAdd(dm, DMRefineHook_DMKSP, NULL, NULL);
110:   }
111:   return 0;
112: }

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

117:    Logically Collective

119:    Input Parameter:
120: .  dm - `DM` used with a `KSP`

122:    Output Parameter:
123: .  kspdm - private `DMKSP` context

125:    Level: developer

127: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`
128: @*/
129: PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
130: {
131:   DMKSP kdm;

134:   DMGetDMKSP(dm, &kdm);
136:   if (kdm->originaldm != dm) { /* Copy on write */
137:     DMKSP oldkdm = kdm;
138:     PetscInfo(dm, "Copying DMKSP due to write\n");
139:     DMKSPCreate(PetscObjectComm((PetscObject)dm), &kdm);
140:     DMKSPCopy(oldkdm, kdm);
141:     DMKSPDestroy((DMKSP *)&dm->dmksp);
142:     dm->dmksp       = (PetscObject)kdm;
143:     kdm->originaldm = dm;
144:   }
145:   *kspdm = kdm;
146:   return 0;
147: }

149: /*@C
150:    DMCopyDMKSP - copies a `DM` `DMKSP` context to a new `DM`

152:    Logically Collective

154:    Input Parameters:
155: +  dmsrc - `DM` to obtain context from
156: -  dmdest - `DM` to add context to

158:    Level: developer

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

163: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`, `KSPSetDM()`
164: @*/
165: PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
166: {
169:   DMKSPDestroy((DMKSP *)&dmdest->dmksp);
170:   dmdest->dmksp = dmsrc->dmksp;
171:   PetscObjectReference(dmdest->dmksp);
172:   DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMKSP, NULL, NULL);
173:   DMRefineHookAdd(dmdest, DMRefineHook_DMKSP, NULL, NULL);
174:   return 0;
175: }

177: /*@C
178:    DMKSPSetComputeOperators - set `KSP` matrix evaluation function

180:    Not Collective

182:    Input Parameters:
183: +  dm - `DM` to be used with `KSP`
184: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
185: -  ctx - context for matrix evaluation

187:    Level: developer

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

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

197: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`
198: @*/
199: PetscErrorCode DMKSPSetComputeOperators(DM dm, PetscErrorCode (*func)(KSP, Mat, Mat, void *), void *ctx)
200: {
201:   DMKSP kdm;

204:   DMGetDMKSPWrite(dm, &kdm);
205:   if (func) kdm->ops->computeoperators = func;
206:   if (ctx) kdm->operatorsctx = ctx;
207:   return 0;
208: }

210: /*@C
211:    DMKSPGetComputeOperators - get `KSP` matrix evaluation function

213:    Not Collective

215:    Input Parameter:
216: .  dm - `DM` used with a `KSP`

218:    Output Parameters:
219: +  func - matrix evaluation function, see `KSPSetComputeOperators()` for calling sequence
220: -  ctx - context for matrix evaluation

222:    Level: developer

224: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`
225: @*/
226: PetscErrorCode DMKSPGetComputeOperators(DM dm, PetscErrorCode (**func)(KSP, Mat, Mat, void *), void *ctx)
227: {
228:   DMKSP kdm;

231:   DMGetDMKSP(dm, &kdm);
232:   if (func) *func = kdm->ops->computeoperators;
233:   if (ctx) *(void **)ctx = kdm->operatorsctx;
234:   return 0;
235: }

237: /*@C
238:    DMKSPSetComputeRHS - set `KSP` right hand side evaluation function

240:    Not Collective

242:    Input Parameters:
243: +  dm - `DM` used with a `KSP`
244: .  func - right hand side evaluation function, see `KSPSetComputeRHS()` for calling sequence
245: -  ctx - context for right hand side evaluation

247:    Level: developer

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

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

257: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
258: @*/
259: PetscErrorCode DMKSPSetComputeRHS(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
260: {
261:   DMKSP kdm;

264:   DMGetDMKSPWrite(dm, &kdm);
265:   if (func) kdm->ops->computerhs = func;
266:   if (ctx) kdm->rhsctx = ctx;
267:   return 0;
268: }

270: /*@C
271:    DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function

273:    Not Collective

275:    Input Parameters:
276: +  dm - `DM` to be used with `KSP`
277: .  func - initial guess evaluation function, see `KSPSetComputeInitialGuess()` for calling sequence
278: -  ctx - context for right hand side evaluation

280:    Level: developer

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

286: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
287: @*/
288: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
289: {
290:   DMKSP kdm;

293:   DMGetDMKSPWrite(dm, &kdm);
294:   if (func) kdm->ops->computeinitialguess = func;
295:   if (ctx) kdm->initialguessctx = ctx;
296:   return 0;
297: }

299: /*@C
300:    DMKSPGetComputeRHS - get `KSP `right hand side evaluation function

302:    Not Collective

304:    Input Parameter:
305: .  dm - `DM` to be used with `KSP`

307:    Output Parameters:
308: +  func - right hand side evaluation function, see `KSPSetComputeRHS()` for calling sequence
309: -  ctx - context for right hand side evaluation

311:    Level: advanced

313: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
314: @*/
315: PetscErrorCode DMKSPGetComputeRHS(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
316: {
317:   DMKSP kdm;

320:   DMGetDMKSP(dm, &kdm);
321:   if (func) *func = kdm->ops->computerhs;
322:   if (ctx) *(void **)ctx = kdm->rhsctx;
323:   return 0;
324: }

326: /*@C
327:    DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function

329:    Not Collective

331:    Input Parameter:
332: .  dm - `DM` used with a `KSP`

334:    Output Parameters:
335: +  func - initial guess evaluation function, see `KSPSetComputeInitialGuess()` for calling sequence
336: -  ctx - context for right hand side evaluation

338:    Level: advanced

340: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
341: @*/
342: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
343: {
344:   DMKSP kdm;

347:   DMGetDMKSP(dm, &kdm);
348:   if (func) *func = kdm->ops->computeinitialguess;
349:   if (ctx) *(void **)ctx = kdm->initialguessctx;
350:   return 0;
351: }