Actual source code: dmksp.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  1: #include <petsc/private/dmimpl.h>
  2: #include <petsc/private/kspimpl.h> /*I "petscksp.h" I*/
  3: #include <petscdm.h>

  7: static PetscErrorCode DMKSPDestroy(DMKSP *kdm)
  8: {

 12:   if (!*kdm) return(0);
 14:   if (--((PetscObject)(*kdm))->refct > 0) {*kdm = 0; return(0);}
 15:   if ((*kdm)->ops->destroy) {((*kdm)->ops->destroy)(kdm);}
 16:   PetscHeaderDestroy(kdm);
 17:   return(0);
 18: }

 22: static PetscErrorCode DMKSPCreate(MPI_Comm comm,DMKSP *kdm)
 23: {

 27:   KSPInitializePackage();
 28:   PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
 29:   return(0);
 30: }


 35: /* Attaches the DMKSP to the coarse level.
 36:  * Under what conditions should we copy versus duplicate?
 37:  */
 38: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
 39: {

 43:   DMCopyDMKSP(dm,dmc);
 44:   return(0);
 45: }

 49: /* Attaches the DMKSP to the coarse level.
 50:  * Under what conditions should we copy versus duplicate?
 51:  */
 52: static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
 53: {

 57:   DMCopyDMKSP(dm,dmc);
 58:   return(0);
 59: }

 63: /*@C
 64:    DMKSPCopy - copies the information in a DMKSP to another DMKSP

 66:    Not Collective

 68:    Input Argument:
 69: +  kdm - Original DMKSP
 70: -  nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()

 72:    Level: developer

 74: .seealso: DMKSPCreate(), DMKSPDestroy()
 75: @*/
 76: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
 77: {

 83:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
 84:   nkdm->ops->computerhs          = kdm->ops->computerhs;
 85:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
 86:   nkdm->ops->destroy             = kdm->ops->destroy;
 87:   nkdm->ops->duplicate           = kdm->ops->duplicate;

 89:   nkdm->operatorsctx    = kdm->operatorsctx;
 90:   nkdm->rhsctx          = kdm->rhsctx;
 91:   nkdm->initialguessctx = kdm->initialguessctx;
 92:   nkdm->data            = kdm->data;

 94:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 95:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 96:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

 98:   /* implementation specific copy hooks */
 99:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
100:   return(0);
101: }

105: /*@C
106:    DMGetDMKSP - get read-only private DMKSP context from a DM

108:    Not Collective

110:    Input Argument:
111: .  dm - DM to be used with KSP

113:    Output Argument:
114: .  snesdm - private DMKSP context

116:    Level: developer

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

121: .seealso: DMGetDMKSPWrite()
122: @*/
123: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
124: {

129:   *kspdm = (DMKSP) dm->dmksp;
130:   if (!*kspdm) {
131:     PetscInfo(dm,"Creating new DMKSP\n");
132:     DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
133:     dm->dmksp = (PetscObject) *kspdm;
134:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
135:     DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
136:   }
137:   return(0);
138: }

142: /*@C
143:    DMGetDMKSPWrite - get write access to private DMKSP context from a DM

145:    Not Collective

147:    Input Argument:
148: .  dm - DM to be used with KSP

150:    Output Argument:
151: .  kspdm - private DMKSP context

153:    Level: developer

155: .seealso: DMGetDMKSP()
156: @*/
157: PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
158: {
160:   DMKSP          kdm;

164:   DMGetDMKSP(dm,&kdm);
165:   if (!kdm->originaldm) kdm->originaldm = dm;
166:   if (kdm->originaldm != dm) {  /* Copy on write */
167:     DMKSP oldkdm = kdm;
168:     PetscInfo(dm,"Copying DMKSP due to write\n");
169:     DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
170:     DMKSPCopy(oldkdm,kdm);
171:     DMKSPDestroy((DMKSP*)&dm->dmksp);
172:     dm->dmksp = (PetscObject)kdm;
173:   }
174:   *kspdm = kdm;
175:   return(0);
176: }

180: /*@C
181:    DMCopyDMKSP - copies a DM context to a new DM

183:    Logically Collective

185:    Input Arguments:
186: +  dmsrc - DM to obtain context from
187: -  dmdest - DM to add context to

189:    Level: developer

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

194: .seealso: DMGetDMKSP(), KSPSetDM()
195: @*/
196: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
197: {

203:   DMKSPDestroy((DMKSP*)&dmdest->dmksp);
204:   dmdest->dmksp = dmsrc->dmksp;
205:   PetscObjectReference(dmdest->dmksp);
206:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
207:   DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
208:   return(0);
209: }

213: /*@C
214:    DMKSPSetComputeOperators - set KSP matrix evaluation function

216:    Not Collective

218:    Input Argument:
219: +  dm - DM to be used with KSP
220: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
221: -  ctx - context for matrix evaluation

223:    Level: advanced

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

230: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
231: @*/
232: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
233: {
235:   DMKSP          kdm;

239:   DMGetDMKSPWrite(dm,&kdm);
240:   if (func) kdm->ops->computeoperators = func;
241:   if (ctx) kdm->operatorsctx = ctx;
242:   return(0);
243: }

247: /*@C
248:    DMKSPGetComputeOperators - get KSP matrix evaluation function

250:    Not Collective

252:    Input Argument:
253: .  dm - DM to be used with KSP

255:    Output Arguments:
256: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
257: -  ctx - context for matrix evaluation

259:    Level: advanced

261: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
262: @*/
263: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
264: {
266:   DMKSP          kdm;

270:   DMGetDMKSP(dm,&kdm);
271:   if (func) *func = kdm->ops->computeoperators;
272:   if (ctx) *(void**)ctx = kdm->operatorsctx;
273:   return(0);
274: }

278: /*@C
279:    DMKSPSetComputeRHS - set KSP right hand side evaluation function

281:    Not Collective

283:    Input Argument:
284: +  dm - DM to be used with KSP
285: .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
286: -  ctx - context for right hand side evaluation

288:    Level: advanced

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

295: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
296: @*/
297: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
298: {
300:   DMKSP          kdm;

304:   DMGetDMKSPWrite(dm,&kdm);
305:   if (func) kdm->ops->computerhs = func;
306:   if (ctx) kdm->rhsctx = ctx;
307:   return(0);
308: }

312: /*@C
313:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function

315:    Not Collective

317:    Input Argument:
318: +  dm - DM to be used with KSP
319: .  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
320: -  ctx - context for right hand side evaluation

322:    Level: advanced

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

328: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
329: @*/
330: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
331: {
333:   DMKSP          kdm;

337:   DMGetDMKSPWrite(dm,&kdm);
338:   if (func) kdm->ops->computeinitialguess = func;
339:   if (ctx) kdm->initialguessctx = ctx;
340:   return(0);
341: }

345: /*@C
346:    DMKSPGetComputeRHS - get KSP right hand side evaluation function

348:    Not Collective

350:    Input Argument:
351: .  dm - DM to be used with KSP

353:    Output Arguments:
354: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
355: -  ctx - context for right hand side evaluation

357:    Level: advanced

359: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
360: @*/
361: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
362: {
364:   DMKSP          kdm;

368:   DMGetDMKSP(dm,&kdm);
369:   if (func) *func = kdm->ops->computerhs;
370:   if (ctx) *(void**)ctx = kdm->rhsctx;
371:   return(0);
372: }

376: /*@C
377:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function

379:    Not Collective

381:    Input Argument:
382: .  dm - DM to be used with KSP

384:    Output Arguments:
385: +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
386: -  ctx - context for right hand side evaluation

388:    Level: advanced

390: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
391: @*/
392: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
393: {
395:   DMKSP          kdm;

399:   DMGetDMKSP(dm,&kdm);
400:   if (func) *func = kdm->ops->computeinitialguess;
401:   if (ctx) *(void**)ctx = kdm->initialguessctx;
402:   return(0);
403: }