Actual source code: dmksp.c
petsc-3.6.4 2016-04-12
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, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
29: return(0);
30: }
35: /* Attaches the DMKSP to the coarse level.
36: * Under what conditions should we copy versus duplicate?
37: */
38: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
39: {
43: DMCopyDMKSP(dm,dmc);
44: return(0);
45: }
49: /* Attaches the DMKSP to the coarse level.
50: * Under what conditions should we copy versus duplicate?
51: */
52: static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
53: {
57: DMCopyDMKSP(dm,dmc);
58: return(0);
59: }
63: /*@C
64: DMKSPCopy - copies the information in a DMKSP to another DMKSP
66: Not Collective
68: Input Argument:
69: + kdm - Original DMKSP
70: - nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()
72: Level: developer
74: .seealso: DMKSPCreate(), DMKSPDestroy()
75: @*/
76: PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
77: {
83: nkdm->ops->computeoperators = kdm->ops->computeoperators;
84: nkdm->ops->computerhs = kdm->ops->computerhs;
85: nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
86: nkdm->ops->destroy = kdm->ops->destroy;
87: nkdm->ops->duplicate = kdm->ops->duplicate;
89: nkdm->operatorsctx = kdm->operatorsctx;
90: nkdm->rhsctx = kdm->rhsctx;
91: nkdm->initialguessctx = kdm->initialguessctx;
92: nkdm->data = kdm->data;
94: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
95: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
96: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
98: /* implementation specific copy hooks */
99: if (kdm->ops->duplicate) {(*kdm->ops->duplicate)(kdm,nkdm);}
100: return(0);
101: }
105: /*@C
106: DMGetDMKSP - get read-only private DMKSP context from a DM
108: Not Collective
110: Input Argument:
111: . dm - DM to be used with KSP
113: Output Argument:
114: . snesdm - private DMKSP context
116: Level: developer
118: Notes:
119: Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.
121: .seealso: DMGetDMKSPWrite()
122: @*/
123: PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
124: {
129: *kspdm = (DMKSP) dm->dmksp;
130: if (!*kspdm) {
131: PetscInfo(dm,"Creating new DMKSP\n");
132: DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);
133: dm->dmksp = (PetscObject) *kspdm;
134: DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);
135: DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);
136: }
137: return(0);
138: }
142: /*@C
143: DMGetDMKSPWrite - get write access to private DMKSP context from a DM
145: Not Collective
147: Input Argument:
148: . dm - DM to be used with KSP
150: Output Argument:
151: . kspdm - private DMKSP context
153: Level: developer
155: .seealso: DMGetDMKSP()
156: @*/
157: PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
158: {
160: DMKSP kdm;
164: DMGetDMKSP(dm,&kdm);
165: if (!kdm->originaldm) kdm->originaldm = dm;
166: if (kdm->originaldm != dm) { /* Copy on write */
167: DMKSP oldkdm = kdm;
168: PetscInfo(dm,"Copying DMKSP due to write\n");
169: DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);
170: DMKSPCopy(oldkdm,kdm);
171: DMKSPDestroy((DMKSP*)&dm->dmksp);
172: dm->dmksp = (PetscObject)kdm;
173: }
174: *kspdm = kdm;
175: return(0);
176: }
180: /*@C
181: DMCopyDMKSP - copies a DM context to a new DM
183: Logically Collective
185: Input Arguments:
186: + dmsrc - DM to obtain context from
187: - dmdest - DM to add context to
189: Level: developer
191: Note:
192: The context is copied by reference. This function does not ensure that a context exists.
194: .seealso: DMGetDMKSP(), KSPSetDM()
195: @*/
196: PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
197: {
203: DMKSPDestroy((DMKSP*)&dmdest->dmksp);
204: dmdest->dmksp = dmsrc->dmksp;
205: PetscObjectReference(dmdest->dmksp);
206: DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);
207: DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);
208: return(0);
209: }
213: /*@C
214: DMKSPSetComputeOperators - set KSP matrix evaluation function
216: Not Collective
218: Input Argument:
219: + dm - DM to be used with KSP
220: . func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
221: - ctx - context for matrix evaluation
223: Level: advanced
225: Note:
226: KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
227: associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
228: not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
230: .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
231: @*/
232: PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
233: {
235: DMKSP kdm;
239: DMGetDMKSPWrite(dm,&kdm);
240: if (func) kdm->ops->computeoperators = func;
241: if (ctx) kdm->operatorsctx = ctx;
242: return(0);
243: }
247: /*@C
248: DMKSPGetComputeOperators - get KSP matrix evaluation function
250: Not Collective
252: Input Argument:
253: . dm - DM to be used with KSP
255: Output Arguments:
256: + func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
257: - ctx - context for matrix evaluation
259: Level: advanced
261: .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
262: @*/
263: PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
264: {
266: DMKSP kdm;
270: DMGetDMKSP(dm,&kdm);
271: if (func) *func = kdm->ops->computeoperators;
272: if (ctx) *(void**)ctx = kdm->operatorsctx;
273: return(0);
274: }
278: /*@C
279: DMKSPSetComputeRHS - set KSP right hand side evaluation function
281: Not Collective
283: Input Argument:
284: + dm - DM to be used with KSP
285: . func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
286: - ctx - context for right hand side evaluation
288: Level: advanced
290: Note:
291: KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
292: associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
293: not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
295: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
296: @*/
297: PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
298: {
300: DMKSP kdm;
304: DMGetDMKSPWrite(dm,&kdm);
305: if (func) kdm->ops->computerhs = func;
306: if (ctx) kdm->rhsctx = ctx;
307: return(0);
308: }
312: /*@C
313: DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function
315: Not Collective
317: Input Argument:
318: + dm - DM to be used with KSP
319: . func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
320: - ctx - context for right hand side evaluation
322: Level: advanced
324: Note:
325: KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
326: associated with the DM.
328: .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
329: @*/
330: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
331: {
333: DMKSP kdm;
337: DMGetDMKSPWrite(dm,&kdm);
338: if (func) kdm->ops->computeinitialguess = func;
339: if (ctx) kdm->initialguessctx = ctx;
340: return(0);
341: }
345: /*@C
346: DMKSPGetComputeRHS - get KSP right hand side evaluation function
348: Not Collective
350: Input Argument:
351: . dm - DM to be used with KSP
353: Output Arguments:
354: + func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
355: - ctx - context for right hand side evaluation
357: Level: advanced
359: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
360: @*/
361: PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
362: {
364: DMKSP kdm;
368: DMGetDMKSP(dm,&kdm);
369: if (func) *func = kdm->ops->computerhs;
370: if (ctx) *(void**)ctx = kdm->rhsctx;
371: return(0);
372: }
376: /*@C
377: DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function
379: Not Collective
381: Input Argument:
382: . dm - DM to be used with KSP
384: Output Arguments:
385: + func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
386: - ctx - context for right hand side evaluation
388: Level: advanced
390: .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
391: @*/
392: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
393: {
395: DMKSP kdm;
399: DMGetDMKSP(dm,&kdm);
400: if (func) *func = kdm->ops->computeinitialguess;
401: if (ctx) *(void**)ctx = kdm->initialguessctx;
402: return(0);
403: }