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: }