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: {

 10:   if (!*kdm) return(0);
 12:   if (--((PetscObject)(*kdm))->refct > 0) {*kdm = NULL; return(0);}
 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: {

 23:   KSPInitializePackage();
 24:   PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
 25:   return(0);
 26: }

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

 36:   DMCopyDMKSP(dm,dmc);
 37:   return(0);
 38: }

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

 48:   DMCopyDMKSP(dm,dmc);
 49:   return(0);
 50: }

 52: /*@C
 53:    DMKSPCopy - copies the information in a DMKSP to another DMKSP

 55:    Not Collective

 57:    Input Parameters:
 58: +  kdm - Original DMKSP
 59: -  nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()

 61:    Level: developer

 63: .seealso: DMKSPCreate(), DMKSPDestroy()
 64: @*/
 65: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
 66: {

 72:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
 73:   nkdm->ops->computerhs          = kdm->ops->computerhs;
 74:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
 75:   nkdm->ops->destroy             = kdm->ops->destroy;
 76:   nkdm->ops->duplicate           = kdm->ops->duplicate;

 78:   nkdm->operatorsctx    = kdm->operatorsctx;
 79:   nkdm->rhsctx          = kdm->rhsctx;
 80:   nkdm->initialguessctx = kdm->initialguessctx;
 81:   nkdm->data            = kdm->data;
 82:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */

 84:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 85:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 86:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

 88:   /* implementation specific copy hooks */
 89:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
 90:   return(0);
 91: }

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

 96:    Logically Collective

 98:    Input Parameter:
 99: .  dm - DM to be used with KSP

101:    Output Parameter:
102: .  snesdm - private DMKSP context

104:    Level: developer

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

109: .seealso: DMGetDMKSPWrite()
110: @*/
111: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
112: {

117:   *kspdm = (DMKSP) dm->dmksp;
118:   if (!*kspdm) {
119:     PetscInfo(dm,"Creating new DMKSP\n");
120:     DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
121:     dm->dmksp            = (PetscObject) *kspdm;
122:     (*kspdm)->originaldm = dm;
123:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
124:     DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
125:   }
126:   return(0);
127: }

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

132:    Logically Collective

134:    Input Parameter:
135: .  dm - DM to be used with KSP

137:    Output Parameter:
138: .  kspdm - private DMKSP context

140:    Level: developer

142: .seealso: DMGetDMKSP()
143: @*/
144: PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
145: {
147:   DMKSP          kdm;

151:   DMGetDMKSP(dm,&kdm);
152:   if (!kdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMKSP has a NULL originaldm");
153:   if (kdm->originaldm != dm) {  /* Copy on write */
154:     DMKSP oldkdm = kdm;
155:     PetscInfo(dm,"Copying DMKSP due to write\n");
156:     DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
157:     DMKSPCopy(oldkdm,kdm);
158:     DMKSPDestroy((DMKSP*)&dm->dmksp);
159:     dm->dmksp = (PetscObject)kdm;
160:     kdm->originaldm = dm;
161:   }
162:   *kspdm = kdm;
163:   return(0);
164: }

166: /*@C
167:    DMCopyDMKSP - copies a DM context to a new DM

169:    Logically Collective

171:    Input Parameters:
172: +  dmsrc - DM to obtain context from
173: -  dmdest - DM to add context to

175:    Level: developer

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

180: .seealso: DMGetDMKSP(), KSPSetDM()
181: @*/
182: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
183: {

189:   DMKSPDestroy((DMKSP*)&dmdest->dmksp);
190:   dmdest->dmksp = dmsrc->dmksp;
191:   PetscObjectReference(dmdest->dmksp);
192:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
193:   DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
194:   return(0);
195: }

197: /*@C
198:    DMKSPSetComputeOperators - set KSP matrix evaluation function

200:    Not Collective

202:    Input Parameters:
203: +  dm - DM to be used with KSP
204: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
205: -  ctx - context for matrix evaluation

207:    Level: advanced

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

214: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
215: @*/
216: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
217: {
219:   DMKSP          kdm;

223:   DMGetDMKSPWrite(dm,&kdm);
224:   if (func) kdm->ops->computeoperators = func;
225:   if (ctx) kdm->operatorsctx = ctx;
226:   return(0);
227: }

229: /*@C
230:    DMKSPGetComputeOperators - get KSP matrix evaluation function

232:    Not Collective

234:    Input Parameter:
235: .  dm - DM to be used with KSP

237:    Output Parameters:
238: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
239: -  ctx - context for matrix evaluation

241:    Level: advanced

243: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
244: @*/
245: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
246: {
248:   DMKSP          kdm;

252:   DMGetDMKSP(dm,&kdm);
253:   if (func) *func = kdm->ops->computeoperators;
254:   if (ctx) *(void**)ctx = kdm->operatorsctx;
255:   return(0);
256: }

258: /*@C
259:    DMKSPSetComputeRHS - set KSP right hand side evaluation function

261:    Not Collective

263:    Input Parameters:
264: +  dm - DM to be used with KSP
265: .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
266: -  ctx - context for right hand side evaluation

268:    Level: advanced

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

275: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
276: @*/
277: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
278: {
280:   DMKSP          kdm;

284:   DMGetDMKSPWrite(dm,&kdm);
285:   if (func) kdm->ops->computerhs = func;
286:   if (ctx) kdm->rhsctx = ctx;
287:   return(0);
288: }

290: /*@C
291:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function

293:    Not Collective

295:    Input Parameters:
296: +  dm - DM to be used with KSP
297: .  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
298: -  ctx - context for right hand side evaluation

300:    Level: advanced

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

306: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
307: @*/
308: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
309: {
311:   DMKSP          kdm;

315:   DMGetDMKSPWrite(dm,&kdm);
316:   if (func) kdm->ops->computeinitialguess = func;
317:   if (ctx) kdm->initialguessctx = ctx;
318:   return(0);
319: }

321: /*@C
322:    DMKSPGetComputeRHS - get KSP right hand side evaluation function

324:    Not Collective

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

329:    Output Parameters:
330: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
331: -  ctx - context for right hand side evaluation

333:    Level: advanced

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

344:   DMGetDMKSP(dm,&kdm);
345:   if (func) *func = kdm->ops->computerhs;
346:   if (ctx) *(void**)ctx = kdm->rhsctx;
347:   return(0);
348: }

350: /*@C
351:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function

353:    Not Collective

355:    Input Parameter:
356: .  dm - DM to be used with KSP

358:    Output Parameters:
359: +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
360: -  ctx - context for right hand side evaluation

362:    Level: advanced

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

373:   DMGetDMKSP(dm,&kdm);
374:   if (func) *func = kdm->ops->computeinitialguess;
375:   if (ctx) *(void**)ctx = kdm->initialguessctx;
376:   return(0);
377: }