Actual source code: dmksp.c

petsc-3.3-p7 2013-05-11
  1: #include <petsc-private/kspimpl.h> /*I "petscksp.h" I*/
  2: #include <petscdm.h>         /*I "petscdm.h"  I*/

  6: static PetscErrorCode PetscContainerDestroy_KSPDM(void *ctx)
  7: {
  9:   KSPDM kdm = (KSPDM)ctx;

 12:   if (kdm->destroy) {(*kdm->destroy)(kdm);}
 13:   PetscFree(kdm);
 14:   return(0);
 15: }

 19: /* Attaches the KSPDM to the coarse level.
 20:  * Under what conditions should we copy versus duplicate?
 21:  */
 22: static PetscErrorCode DMCoarsenHook_KSPDM(DM dm,DM dmc,void *ctx)
 23: {

 27:   DMKSPCopyContext(dm,dmc);
 28:   return(0);
 29: }

 33: /*@C
 34:    DMKSPGetContext - get read-only private KSPDM context from a DM

 36:    Not Collective

 38:    Input Argument:
 39: .  dm - DM to be used with KSP

 41:    Output Argument:
 42: .  snesdm - private KSPDM context

 44:    Level: developer

 46:    Notes:
 47:    Use DMKSPGetContextWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.

 49: .seealso: DMKSPGetContextWrite()
 50: @*/
 51: PetscErrorCode DMKSPGetContext(DM dm,KSPDM *snesdm)
 52: {
 54:   PetscContainer container;
 55:   KSPDM         kdm;

 59:   PetscObjectQuery((PetscObject)dm,"KSPDM",(PetscObject*)&container);
 60:   if (container) {
 61:     PetscContainerGetPointer(container,(void**)snesdm);
 62:   } else {
 63:     PetscInfo(dm,"Creating new KSPDM\n");
 64:     PetscContainerCreate(((PetscObject)dm)->comm,&container);
 65:     PetscNewLog(dm,struct _n_KSPDM,&kdm);
 66:     PetscContainerSetPointer(container,kdm);
 67:     PetscContainerSetUserDestroy(container,PetscContainerDestroy_KSPDM);
 68:     PetscObjectCompose((PetscObject)dm,"KSPDM",(PetscObject)container);
 69:     DMCoarsenHookAdd(dm,DMCoarsenHook_KSPDM,PETSC_NULL,PETSC_NULL);
 70:     PetscContainerGetPointer(container,(void**)snesdm);
 71:     PetscContainerDestroy(&container);
 72:   }
 73:   return(0);
 74: }

 78: /*@C
 79:    DMKSPGetContextWrite - get write access to private KSPDM context from a DM

 81:    Not Collective

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

 86:    Output Argument:
 87: .  snesdm - private KSPDM context

 89:    Level: developer

 91: .seealso: DMKSPGetContext()
 92: @*/
 93: PetscErrorCode DMKSPGetContextWrite(DM dm,KSPDM *snesdm)
 94: {
 96:   KSPDM         kdm;

100:   DMKSPGetContext(dm,&kdm);
101:   if (!kdm->originaldm) kdm->originaldm = dm;
102:   if (kdm->originaldm != dm) {  /* Copy on write */
103:     PetscContainer container;
104:     KSPDM         oldsdm = kdm;
105:     PetscInfo(dm,"Copying KSPDM due to write\n");
106:     PetscContainerCreate(((PetscObject)dm)->comm,&container);
107:     PetscNewLog(dm,struct _n_KSPDM,&kdm);
108:     PetscMemcpy(kdm,oldsdm,sizeof *kdm);
109:     PetscContainerSetPointer(container,kdm);
110:     PetscContainerSetUserDestroy(container,PetscContainerDestroy_KSPDM);
111:     PetscObjectCompose((PetscObject)dm,"KSPDM",(PetscObject)container);
112:     PetscContainerDestroy(&container);
113:   }
114:   *snesdm = kdm;
115:   return(0);
116: }

120: /*@C
121:    DMKSPCopyContext - copies a DM context to a new DM

123:    Logically Collective

125:    Input Arguments:
126: +  dmsrc - DM to obtain context from
127: -  dmdest - DM to add context to

129:    Level: developer

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

134: .seealso: DMKSPGetContext(), KSPSetDM()
135: @*/
136: PetscErrorCode DMKSPCopyContext(DM dmsrc,DM dmdest)
137: {
139:   PetscContainer container;

144:   PetscObjectQuery((PetscObject)dmsrc,"KSPDM",(PetscObject*)&container);
145:   if (container) {
146:     PetscObjectCompose((PetscObject)dmdest,"KSPDM",(PetscObject)container);
147:     DMCoarsenHookAdd(dmdest,DMCoarsenHook_KSPDM,PETSC_NULL,PETSC_NULL);
148:   }
149:   return(0);
150: }

154: /*@C
155:    DMKSPSetComputeOperators - set KSP matrix evaluation function

157:    Not Collective

159:    Input Argument:
160: +  dm - DM to be used with KSP
161: .  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
162: -  ctx - context for matrix evaluation

164:    Level: advanced

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

171: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
172: @*/
173: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,MatStructure*,void*),void *ctx)
174: {
176:   KSPDM kdm;

180:   DMKSPGetContextWrite(dm,&kdm);
181:   if (func) kdm->computeoperators = func;
182:   if (ctx)  kdm->operatorsctx = ctx;
183:   return(0);
184: }

188: /*@C
189:    DMKSPGetComputeOperators - get KSP matrix evaluation function

191:    Not Collective

193:    Input Argument:
194: .  dm - DM to be used with KSP

196:    Output Arguments:
197: +  func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
198: -  ctx - context for matrix evaluation

200:    Level: advanced

202: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
203: @*/
204: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,MatStructure*,void*),void *ctx)
205: {
207:   KSPDM kdm;

211:   DMKSPGetContext(dm,&kdm);
212:   if (func) *func = kdm->computeoperators;
213:   if (ctx)  *(void**)ctx = kdm->operatorsctx;
214:   return(0);
215: }

219: /*@C
220:    DMKSPSetComputeRHS - set KSP matrix evaluation function

222:    Not Collective

224:    Input Argument:
225: +  dm - DM to be used with KSP
226: .  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
227: -  ctx - context for right hand side evaluation

229:    Level: advanced

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

236: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
237: @*/
238: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
239: {
241:   KSPDM kdm;

245:   DMKSPGetContextWrite(dm,&kdm);
246:   if (func) kdm->computerhs = func;
247:   if (ctx)  kdm->rhsctx = ctx;
248:   return(0);
249: }

253: /*@C
254:    DMKSPGetComputeRHS - get KSP matrix evaluation function

256:    Not Collective

258:    Input Argument:
259: .  dm - DM to be used with KSP

261:    Output Arguments:
262: +  func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
263: -  ctx - context for right hand side evaluation

265:    Level: advanced

267: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
268: @*/
269: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
270: {
272:   KSPDM kdm;

276:   DMKSPGetContext(dm,&kdm);
277:   if (func) *func = kdm->computerhs;
278:   if (ctx)  *(void**)ctx = kdm->rhsctx;
279:   return(0);
280: }