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, should have been created with DMKSPCreate()

 52:    Level: developer

 54: .seealso: `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 to be used with KSP

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

 92:    Level: developer

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

 97: .seealso: `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 to be used with KSP

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

125:    Level: developer

127: .seealso: `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 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: `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: advanced

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. If DM took a more central role at some later date, this could become the primary method of setting the matrix.

194: .seealso: `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`
195: @*/
196: PetscErrorCode DMKSPSetComputeOperators(DM dm, PetscErrorCode (*func)(KSP, Mat, Mat, void *), void *ctx)
197: {
198:   DMKSP kdm;

201:   DMGetDMKSPWrite(dm, &kdm);
202:   if (func) kdm->ops->computeoperators = func;
203:   if (ctx) kdm->operatorsctx = ctx;
204:   return 0;
205: }

207: /*@C
208:    DMKSPGetComputeOperators - get KSP matrix evaluation function

210:    Not Collective

212:    Input Parameter:
213: .  dm - DM to be used with KSP

215:    Output Parameters:
216: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
217: -  ctx - context for matrix evaluation

219:    Level: advanced

221: .seealso: `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`
222: @*/
223: PetscErrorCode DMKSPGetComputeOperators(DM dm, PetscErrorCode (**func)(KSP, Mat, Mat, void *), void *ctx)
224: {
225:   DMKSP kdm;

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

234: /*@C
235:    DMKSPSetComputeRHS - set KSP right hand side evaluation function

237:    Not Collective

239:    Input Parameters:
240: +  dm - DM to be used with KSP
241: .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
242: -  ctx - context for right hand side evaluation

244:    Level: advanced

246:    Note:
247:    KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
248:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
249:    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.

251: .seealso: `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
252: @*/
253: PetscErrorCode DMKSPSetComputeRHS(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
254: {
255:   DMKSP kdm;

258:   DMGetDMKSPWrite(dm, &kdm);
259:   if (func) kdm->ops->computerhs = func;
260:   if (ctx) kdm->rhsctx = ctx;
261:   return 0;
262: }

264: /*@C
265:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function

267:    Not Collective

269:    Input Parameters:
270: +  dm - DM to be used with KSP
271: .  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
272: -  ctx - context for right hand side evaluation

274:    Level: advanced

276:    Note:
277:    KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
278:    associated with the DM.

280: .seealso: `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
281: @*/
282: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
283: {
284:   DMKSP kdm;

287:   DMGetDMKSPWrite(dm, &kdm);
288:   if (func) kdm->ops->computeinitialguess = func;
289:   if (ctx) kdm->initialguessctx = ctx;
290:   return 0;
291: }

293: /*@C
294:    DMKSPGetComputeRHS - get KSP right hand side evaluation function

296:    Not Collective

298:    Input Parameter:
299: .  dm - DM to be used with KSP

301:    Output Parameters:
302: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
303: -  ctx - context for right hand side evaluation

305:    Level: advanced

307: .seealso: `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
308: @*/
309: PetscErrorCode DMKSPGetComputeRHS(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
310: {
311:   DMKSP kdm;

314:   DMGetDMKSP(dm, &kdm);
315:   if (func) *func = kdm->ops->computerhs;
316:   if (ctx) *(void **)ctx = kdm->rhsctx;
317:   return 0;
318: }

320: /*@C
321:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function

323:    Not Collective

325:    Input Parameter:
326: .  dm - DM to be used with KSP

328:    Output Parameters:
329: +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
330: -  ctx - context for right hand side evaluation

332:    Level: advanced

334: .seealso: `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
335: @*/
336: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
337: {
338:   DMKSP kdm;

341:   DMGetDMKSP(dm, &kdm);
342:   if (func) *func = kdm->ops->computeinitialguess;
343:   if (ctx) *(void **)ctx = kdm->initialguessctx;
344:   return 0;
345: }