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: }
 29: /* Attaches the DMKSP to the coarse level.
 30:  * Under what conditions should we copy versus duplicate?
 31:  */
 32: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
 33: {
 37:   DMCopyDMKSP(dm,dmc);
 38:   return(0);
 39: }
 41: /* Attaches the DMKSP to the coarse level.
 42:  * Under what conditions should we copy versus duplicate?
 43:  */
 44: static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
 45: {
 49:   DMCopyDMKSP(dm,dmc);
 50:   return(0);
 51: }
 53: /*@C
 54:    DMKSPCopy - copies the information in a DMKSP to another DMKSP
 56:    Not Collective
 58:    Input Argument:
 59: +  kdm - Original DMKSP
 60: -  nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()
 62:    Level: developer
 64: .seealso: DMKSPCreate(), DMKSPDestroy()
 65: @*/
 66: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
 67: {
 73:   nkdm->ops->computeoperators    = kdm->ops->computeoperators;
 74:   nkdm->ops->computerhs          = kdm->ops->computerhs;
 75:   nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
 76:   nkdm->ops->destroy             = kdm->ops->destroy;
 77:   nkdm->ops->duplicate           = kdm->ops->duplicate;
 79:   nkdm->operatorsctx    = kdm->operatorsctx;
 80:   nkdm->rhsctx          = kdm->rhsctx;
 81:   nkdm->initialguessctx = kdm->initialguessctx;
 82:   nkdm->data            = kdm->data;
 83:   /* nkdm->originaldm   = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */
 85:   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
 86:   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
 87:   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
 89:   /* implementation specific copy hooks */
 90:   if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
 91:   return(0);
 92: }
 94: /*@C
 95:    DMGetDMKSP - get read-only private DMKSP context from a DM
 97:    Logically Collective
 99:    Input Argument:
100: .  dm - DM to be used with KSP
102:    Output Argument:
103: .  snesdm - private DMKSP context
105:    Level: developer
107:    Notes:
108:    Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.
110: .seealso: DMGetDMKSPWrite()
111: @*/
112: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
113: {
118:   *kspdm = (DMKSP) dm->dmksp;
119:   if (!*kspdm) {
120:     PetscInfo(dm,"Creating new DMKSP\n");
121:     DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
122:     dm->dmksp            = (PetscObject) *kspdm;
123:     (*kspdm)->originaldm = dm;
124:     DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
125:     DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
126:   }
127:   return(0);
128: }
130: /*@C
131:    DMGetDMKSPWrite - get write access to private DMKSP context from a DM
133:    Logically Collective
135:    Input Argument:
136: .  dm - DM to be used with KSP
138:    Output Argument:
139: .  kspdm - private DMKSP context
141:    Level: developer
143: .seealso: DMGetDMKSP()
144: @*/
145: PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
146: {
148:   DMKSP          kdm;
152:   DMGetDMKSP(dm,&kdm);
153:   if (!kdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMKSP has a NULL originaldm");
154:   if (kdm->originaldm != dm) {  /* Copy on write */
155:     DMKSP oldkdm = kdm;
156:     PetscInfo(dm,"Copying DMKSP due to write\n");
157:     DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
158:     DMKSPCopy(oldkdm,kdm);
159:     DMKSPDestroy((DMKSP*)&dm->dmksp);
160:     dm->dmksp = (PetscObject)kdm;
161:     kdm->originaldm = dm;
162:   }
163:   *kspdm = kdm;
164:   return(0);
165: }
167: /*@C
168:    DMCopyDMKSP - copies a DM context to a new DM
170:    Logically Collective
172:    Input Arguments:
173: +  dmsrc - DM to obtain context from
174: -  dmdest - DM to add context to
176:    Level: developer
178:    Note:
179:    The context is copied by reference. This function does not ensure that a context exists.
181: .seealso: DMGetDMKSP(), KSPSetDM()
182: @*/
183: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
184: {
190:   DMKSPDestroy((DMKSP*)&dmdest->dmksp);
191:   dmdest->dmksp = dmsrc->dmksp;
192:   PetscObjectReference(dmdest->dmksp);
193:   DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
194:   DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
195:   return(0);
196: }
198: /*@C
199:    DMKSPSetComputeOperators - set KSP matrix evaluation function
201:    Not Collective
203:    Input Argument:
204: +  dm - DM to be used with KSP
205: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
206: -  ctx - context for matrix evaluation
208:    Level: advanced
210:    Note:
211:    KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
212:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
213:    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
215: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
216: @*/
217: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
218: {
220:   DMKSP          kdm;
224:   DMGetDMKSPWrite(dm,&kdm);
225:   if (func) kdm->ops->computeoperators = func;
226:   if (ctx) kdm->operatorsctx = ctx;
227:   return(0);
228: }
230: /*@C
231:    DMKSPGetComputeOperators - get KSP matrix evaluation function
233:    Not Collective
235:    Input Argument:
236: .  dm - DM to be used with KSP
238:    Output Arguments:
239: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
240: -  ctx - context for matrix evaluation
242:    Level: advanced
244: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
245: @*/
246: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
247: {
249:   DMKSP          kdm;
253:   DMGetDMKSP(dm,&kdm);
254:   if (func) *func = kdm->ops->computeoperators;
255:   if (ctx) *(void**)ctx = kdm->operatorsctx;
256:   return(0);
257: }
259: /*@C
260:    DMKSPSetComputeRHS - set KSP right hand side evaluation function
262:    Not Collective
264:    Input Argument:
265: +  dm - DM to be used with KSP
266: .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
267: -  ctx - context for right hand side evaluation
269:    Level: advanced
271:    Note:
272:    KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
273:    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
274:    not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
276: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
277: @*/
278: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
279: {
281:   DMKSP          kdm;
285:   DMGetDMKSPWrite(dm,&kdm);
286:   if (func) kdm->ops->computerhs = func;
287:   if (ctx) kdm->rhsctx = ctx;
288:   return(0);
289: }
291: /*@C
292:    DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function
294:    Not Collective
296:    Input Argument:
297: +  dm - DM to be used with KSP
298: .  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
299: -  ctx - context for right hand side evaluation
301:    Level: advanced
303:    Note:
304:    KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
305:    associated with the DM.
307: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
308: @*/
309: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
310: {
312:   DMKSP          kdm;
316:   DMGetDMKSPWrite(dm,&kdm);
317:   if (func) kdm->ops->computeinitialguess = func;
318:   if (ctx) kdm->initialguessctx = ctx;
319:   return(0);
320: }
322: /*@C
323:    DMKSPGetComputeRHS - get KSP right hand side evaluation function
325:    Not Collective
327:    Input Argument:
328: .  dm - DM to be used with KSP
330:    Output Arguments:
331: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
332: -  ctx - context for right hand side evaluation
334:    Level: advanced
336: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
337: @*/
338: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
339: {
341:   DMKSP          kdm;
345:   DMGetDMKSP(dm,&kdm);
346:   if (func) *func = kdm->ops->computerhs;
347:   if (ctx) *(void**)ctx = kdm->rhsctx;
348:   return(0);
349: }
351: /*@C
352:    DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function
354:    Not Collective
356:    Input Argument:
357: .  dm - DM to be used with KSP
359:    Output Arguments:
360: +  func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
361: -  ctx - context for right hand side evaluation
363:    Level: advanced
365: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
366: @*/
367: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
368: {
370:   DMKSP          kdm;
374:   DMGetDMKSP(dm,&kdm);
375:   if (func) *func = kdm->ops->computeinitialguess;
376:   if (ctx) *(void**)ctx = kdm->initialguessctx;
377:   return(0);
378: }