Actual source code: dmksp.c

petsc-3.5.2 2014-09-08
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, _p_DMKSP, struct _DMKSPOps, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
 29:   PetscMemzero((*kdm)->ops, sizeof(struct _DMKSPOps));
 30:   return(0);
 31: }


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

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

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

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

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

 67:    Not Collective

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

 73:    Level: developer

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

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

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

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

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

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

109:    Not Collective

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

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

117:    Level: developer

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

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

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

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

146:    Not Collective

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

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

154:    Level: developer

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

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

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

184:    Logically Collective

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

190:    Level: developer

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

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

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

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

217:    Not Collective

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

224:    Level: advanced

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

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

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

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

251:    Not Collective

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

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

260:    Level: advanced

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

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

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

282:    Not Collective

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

289:    Level: advanced

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

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

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

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

316:    Not Collective

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

323:    Level: advanced

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

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

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

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

349:    Not Collective

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

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

358:    Level: advanced

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

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

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

380:    Not Collective

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

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

389:    Level: advanced

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

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