Actual source code: dmksp.c

petsc-3.4.4 2014-03-13
  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: #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
 28:   KSPInitializePackage();
 29: #endif
 30:   PetscHeaderCreate(*kdm, _p_DMKSP, struct _DMKSPOps, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
 31:   PetscMemzero((*kdm)->ops, sizeof(struct _DMKSPOps));
 32:   return(0);
 33: }


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

 46:   DMCopyDMKSP(dm,dmc);
 47:   return(0);
 48: }

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

 60:   DMCopyDMKSP(dm,dmc);
 61:   return(0);
 62: }

 66: /*@C
 67:    DMKSPCopy - copies the information in a DMKSP to another DMKSP

 69:    Not Collective

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

 75:    Level: developer

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

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

 92:   nkdm->operatorsctx    = kdm->operatorsctx;
 93:   nkdm->rhsctx          = kdm->rhsctx;
 94:   nkdm->initialguessctx = kdm->initialguessctx;
 95:   nkdm->data            = kdm->data;

 97:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 98:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 99:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

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

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

111:    Not Collective

113:    Input Argument:
114: .  dm - DM to be used with KSP

116:    Output Argument:
117: .  snesdm - private DMKSP context

119:    Level: developer

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

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

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

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

148:    Not Collective

150:    Input Argument:
151: .  dm - DM to be used with KSP

153:    Output Argument:
154: .  kspdm - private DMKSP context

156:    Level: developer

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

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

183: /*@C
184:    DMCopyDMKSP - copies a DM context to a new DM

186:    Logically Collective

188:    Input Arguments:
189: +  dmsrc - DM to obtain context from
190: -  dmdest - DM to add context to

192:    Level: developer

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

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

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

216: /*@C
217:    DMKSPSetComputeOperators - set KSP matrix evaluation function

219:    Not Collective

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

226:    Level: advanced

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

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

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

250: /*@C
251:    DMKSPGetComputeOperators - get KSP matrix evaluation function

253:    Not Collective

255:    Input Argument:
256: .  dm - DM to be used with KSP

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

262:    Level: advanced

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

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

281: /*@C
282:    DMKSPSetComputeRHS - set KSP right hand side evaluation function

284:    Not Collective

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

291:    Level: advanced

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

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

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

315: /*@C
316:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function

318:    Not Collective

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

325:    Level: advanced

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

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

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

348: /*@C
349:    DMKSPGetComputeRHS - get KSP right hand side evaluation function

351:    Not Collective

353:    Input Argument:
354: .  dm - DM to be used with KSP

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

360:    Level: advanced

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

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

379: /*@C
380:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function

382:    Not Collective

384:    Input Argument:
385: .  dm - DM to be used with KSP

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

391:    Level: advanced

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

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