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) {*kdm = NULL; return 0;}
 10:   if ((*kdm)->ops->destroy) ((*kdm)->ops->destroy)(kdm);
 11:   PetscHeaderDestroy(kdm);
 12:   return 0;
 13: }

 15: static PetscErrorCode DMKSPCreate(MPI_Comm comm,DMKSP *kdm)
 16: {
 17:   KSPInitializePackage();
 18:   PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
 19:   return 0;
 20: }

 22: /* Attaches the DMKSP to the coarse level.
 23:  * Under what conditions should we copy versus duplicate?
 24:  */
 25: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
 26: {
 27:   DMCopyDMKSP(dm,dmc);
 28:   return 0;
 29: }

 31: /* Attaches the DMKSP to the coarse level.
 32:  * Under what conditions should we copy versus duplicate?
 33:  */
 34: static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
 35: {
 36:   DMCopyDMKSP(dm,dmc);
 37:   return 0;
 38: }

 40: /*@C
 41:    DMKSPCopy - copies the information in a DMKSP to another DMKSP

 43:    Not Collective

 45:    Input Parameters:
 46: +  kdm - Original DMKSP
 47: -  nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()

 49:    Level: developer

 51: .seealso: DMKSPCreate(), DMKSPDestroy()
 52: @*/
 53: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
 54: {
 57:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
 58:   nkdm->ops->computerhs          = kdm->ops->computerhs;
 59:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
 60:   nkdm->ops->destroy             = kdm->ops->destroy;
 61:   nkdm->ops->duplicate           = kdm->ops->duplicate;

 63:   nkdm->operatorsctx    = kdm->operatorsctx;
 64:   nkdm->rhsctx          = kdm->rhsctx;
 65:   nkdm->initialguessctx = kdm->initialguessctx;
 66:   nkdm->data            = kdm->data;
 67:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */

 69:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 70:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 71:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];

 73:   /* implementation specific copy hooks */
 74:   if (kdm->ops->duplicate) (*kdm->ops->duplicate)(kdm,nkdm);
 75:   return 0;
 76: }

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

 81:    Logically Collective

 83:    Input Parameter:
 84: .  dm - DM to be used with KSP

 86:    Output Parameter:
 87: .  snesdm - private DMKSP context

 89:    Level: developer

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

 94: .seealso: DMGetDMKSPWrite()
 95: @*/
 96: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
 97: {
 99:   *kspdm = (DMKSP) dm->dmksp;
100:   if (!*kspdm) {
101:     PetscInfo(dm,"Creating new DMKSP\n");
102:     DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
103:     dm->dmksp            = (PetscObject) *kspdm;
104:     (*kspdm)->originaldm = dm;
105:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
106:     DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
107:   }
108:   return 0;
109: }

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

114:    Logically Collective

116:    Input Parameter:
117: .  dm - DM to be used with KSP

119:    Output Parameter:
120: .  kspdm - private DMKSP context

122:    Level: developer

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

131:   DMGetDMKSP(dm,&kdm);
133:   if (kdm->originaldm != dm) {  /* Copy on write */
134:     DMKSP oldkdm = kdm;
135:     PetscInfo(dm,"Copying DMKSP due to write\n");
136:     DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
137:     DMKSPCopy(oldkdm,kdm);
138:     DMKSPDestroy((DMKSP*)&dm->dmksp);
139:     dm->dmksp = (PetscObject)kdm;
140:     kdm->originaldm = dm;
141:   }
142:   *kspdm = kdm;
143:   return 0;
144: }

146: /*@C
147:    DMCopyDMKSP - copies a DM context to a new DM

149:    Logically Collective

151:    Input Parameters:
152: +  dmsrc - DM to obtain context from
153: -  dmdest - DM to add context to

155:    Level: developer

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

160: .seealso: DMGetDMKSP(), KSPSetDM()
161: @*/
162: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
163: {
166:   DMKSPDestroy((DMKSP*)&dmdest->dmksp);
167:   dmdest->dmksp = dmsrc->dmksp;
168:   PetscObjectReference(dmdest->dmksp);
169:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
170:   DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
171:   return 0;
172: }

174: /*@C
175:    DMKSPSetComputeOperators - set KSP matrix evaluation function

177:    Not Collective

179:    Input Parameters:
180: +  dm - DM to be used with KSP
181: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
182: -  ctx - context for matrix evaluation

184:    Level: advanced

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

191: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
192: @*/
193: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
194: {
195:   DMKSP          kdm;

198:   DMGetDMKSPWrite(dm,&kdm);
199:   if (func) kdm->ops->computeoperators = func;
200:   if (ctx) kdm->operatorsctx = ctx;
201:   return 0;
202: }

204: /*@C
205:    DMKSPGetComputeOperators - get KSP matrix evaluation function

207:    Not Collective

209:    Input Parameter:
210: .  dm - DM to be used with KSP

212:    Output Parameters:
213: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
214: -  ctx - context for matrix evaluation

216:    Level: advanced

218: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
219: @*/
220: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
221: {
222:   DMKSP          kdm;

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

231: /*@C
232:    DMKSPSetComputeRHS - set KSP right hand side evaluation function

234:    Not Collective

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

241:    Level: advanced

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

248: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
249: @*/
250: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
251: {
252:   DMKSP          kdm;

255:   DMGetDMKSPWrite(dm,&kdm);
256:   if (func) kdm->ops->computerhs = func;
257:   if (ctx) kdm->rhsctx = ctx;
258:   return 0;
259: }

261: /*@C
262:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function

264:    Not Collective

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

271:    Level: advanced

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

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

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

290: /*@C
291:    DMKSPGetComputeRHS - get KSP right hand side evaluation function

293:    Not Collective

295:    Input Parameter:
296: .  dm - DM to be used with KSP

298:    Output Parameters:
299: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
300: -  ctx - context for right hand side evaluation

302:    Level: advanced

304: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
305: @*/
306: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
307: {
308:   DMKSP          kdm;

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

317: /*@C
318:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function

320:    Not Collective

322:    Input Parameter:
323: .  dm - DM to be used with KSP

325:    Output Parameters:
326: +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
327: -  ctx - context for right hand side evaluation

329:    Level: advanced

331: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
332: @*/
333: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
334: {
335:   DMKSP          kdm;

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