Actual source code: dmksp.c
petsc-3.5.4 2015-05-23
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: KSPInitializePackage();
28: PetscHeaderCreate(*kdm, _p_DMKSP, struct _DMKSPOps, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
29: PetscMemzero((*kdm)->ops, sizeof(struct _DMKSPOps));
30: return(0);
31: }
36: /* Attaches the DMKSP to the coarse level.
37: * Under what conditions should we copy versus duplicate?
38: */
39: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
40: {
44: DMCopyDMKSP(dm,dmc);
45: return(0);
46: }
50: /* Attaches the DMKSP to the coarse level.
51: * Under what conditions should we copy versus duplicate?
52: */
53: static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
54: {
58: DMCopyDMKSP(dm,dmc);
59: return(0);
60: }
64: /*@C
65: DMKSPCopy - copies the information in a DMKSP to another DMKSP
67: Not Collective
69: Input Argument:
70: + kdm - Original DMKSP
71: - nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()
73: Level: developer
75: .seealso: DMKSPCreate(), DMKSPDestroy()
76: @*/
77: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
78: {
84: nkdm->ops->computeoperators = kdm->ops->computeoperators;
85: nkdm->ops->computerhs = kdm->ops->computerhs;
86: nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
87: nkdm->ops->destroy = kdm->ops->destroy;
88: nkdm->ops->duplicate = kdm->ops->duplicate;
90: nkdm->operatorsctx = kdm->operatorsctx;
91: nkdm->rhsctx = kdm->rhsctx;
92: nkdm->initialguessctx = kdm->initialguessctx;
93: nkdm->data = kdm->data;
95: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
96: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
97: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
99: /* implementation specific copy hooks */
100: if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
101: return(0);
102: }
106: /*@C
107: DMGetDMKSP - get read-only private DMKSP context from a DM
109: Not Collective
111: Input Argument:
112: . dm - DM to be used with KSP
114: Output Argument:
115: . snesdm - private DMKSP context
117: Level: developer
119: Notes:
120: Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.
122: .seealso: DMGetDMKSPWrite()
123: @*/
124: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
125: {
130: *kspdm = (DMKSP) dm->dmksp;
131: if (!*kspdm) {
132: PetscInfo(dm,"Creating new DMKSP\n");
133: DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
134: dm->dmksp = (PetscObject) *kspdm;
135: DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
136: DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
137: }
138: return(0);
139: }
143: /*@C
144: DMGetDMKSPWrite - get write access to private DMKSP context from a DM
146: Not Collective
148: Input Argument:
149: . dm - DM to be used with KSP
151: Output Argument:
152: . kspdm - private DMKSP context
154: Level: developer
156: .seealso: DMGetDMKSP()
157: @*/
158: PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
159: {
161: DMKSP kdm;
165: DMGetDMKSP(dm,&kdm);
166: if (!kdm->originaldm) kdm->originaldm = dm;
167: if (kdm->originaldm != dm) { /* Copy on write */
168: DMKSP oldkdm = kdm;
169: PetscInfo(dm,"Copying DMKSP due to write\n");
170: DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
171: DMKSPCopy(oldkdm,kdm);
172: DMKSPDestroy((DMKSP*)&dm->dmksp);
173: dm->dmksp = (PetscObject)kdm;
174: }
175: *kspdm = kdm;
176: return(0);
177: }
181: /*@C
182: DMCopyDMKSP - copies a DM context to a new DM
184: Logically Collective
186: Input Arguments:
187: + dmsrc - DM to obtain context from
188: - dmdest - DM to add context to
190: Level: developer
192: Note:
193: The context is copied by reference. This function does not ensure that a context exists.
195: .seealso: DMGetDMKSP(), KSPSetDM()
196: @*/
197: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
198: {
204: DMKSPDestroy((DMKSP*)&dmdest->dmksp);
205: dmdest->dmksp = dmsrc->dmksp;
206: PetscObjectReference(dmdest->dmksp);
207: DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
208: DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
209: return(0);
210: }
214: /*@C
215: DMKSPSetComputeOperators - set KSP matrix evaluation function
217: Not Collective
219: Input Argument:
220: + dm - DM to be used with KSP
221: . func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
222: - ctx - context for matrix evaluation
224: Level: advanced
226: Note:
227: KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
228: associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
229: not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
231: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
232: @*/
233: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
234: {
236: DMKSP kdm;
240: DMGetDMKSPWrite(dm,&kdm);
241: if (func) kdm->ops->computeoperators = func;
242: if (ctx) kdm->operatorsctx = ctx;
243: return(0);
244: }
248: /*@C
249: DMKSPGetComputeOperators - get KSP matrix evaluation function
251: Not Collective
253: Input Argument:
254: . dm - DM to be used with KSP
256: Output Arguments:
257: + func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
258: - ctx - context for matrix evaluation
260: Level: advanced
262: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
263: @*/
264: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
265: {
267: DMKSP kdm;
271: DMGetDMKSP(dm,&kdm);
272: if (func) *func = kdm->ops->computeoperators;
273: if (ctx) *(void**)ctx = kdm->operatorsctx;
274: return(0);
275: }
279: /*@C
280: DMKSPSetComputeRHS - set KSP right hand side evaluation function
282: Not Collective
284: Input Argument:
285: + dm - DM to be used with KSP
286: . func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
287: - ctx - context for right hand side evaluation
289: Level: advanced
291: Note:
292: KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
293: associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
294: not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
296: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
297: @*/
298: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
299: {
301: DMKSP kdm;
305: DMGetDMKSPWrite(dm,&kdm);
306: if (func) kdm->ops->computerhs = func;
307: if (ctx) kdm->rhsctx = ctx;
308: return(0);
309: }
313: /*@C
314: DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function
316: Not Collective
318: Input Argument:
319: + dm - DM to be used with KSP
320: . func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
321: - ctx - context for right hand side evaluation
323: Level: advanced
325: Note:
326: KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
327: associated with the DM.
329: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
330: @*/
331: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
332: {
334: DMKSP kdm;
338: DMGetDMKSPWrite(dm,&kdm);
339: if (func) kdm->ops->computeinitialguess = func;
340: if (ctx) kdm->initialguessctx = ctx;
341: return(0);
342: }
346: /*@C
347: DMKSPGetComputeRHS - get KSP right hand side evaluation function
349: Not Collective
351: Input Argument:
352: . dm - DM to be used with KSP
354: Output Arguments:
355: + func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
356: - ctx - context for right hand side evaluation
358: Level: advanced
360: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
361: @*/
362: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
363: {
365: DMKSP kdm;
369: DMGetDMKSP(dm,&kdm);
370: if (func) *func = kdm->ops->computerhs;
371: if (ctx) *(void**)ctx = kdm->rhsctx;
372: return(0);
373: }
377: /*@C
378: DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function
380: Not Collective
382: Input Argument:
383: . dm - DM to be used with KSP
385: Output Arguments:
386: + func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
387: - ctx - context for right hand side evaluation
389: Level: advanced
391: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
392: @*/
393: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
394: {
396: DMKSP kdm;
400: DMGetDMKSP(dm,&kdm);
401: if (func) *func = kdm->ops->computeinitialguess;
402: if (ctx) *(void**)ctx = kdm->initialguessctx;
403: return(0);
404: }