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) {
10: *kdm = NULL;
11: return 0;
12: }
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: {
20: KSPInitializePackage();
21: PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);
22: return 0;
23: }
25: /* Attaches the DMKSP to the coarse level.
26: * Under what conditions should we copy versus duplicate?
27: */
28: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm, DM dmc, void *ctx)
29: {
30: DMCopyDMKSP(dm, dmc);
31: return 0;
32: }
34: /* Attaches the DMKSP to the coarse level.
35: * Under what conditions should we copy versus duplicate?
36: */
37: static PetscErrorCode DMRefineHook_DMKSP(DM dm, DM dmc, void *ctx)
38: {
39: DMCopyDMKSP(dm, dmc);
40: return 0;
41: }
43: /*@C
44: DMKSPCopy - copies the information in a DMKSP to another DMKSP
46: Not Collective
48: Input Parameters:
49: + kdm - Original DMKSP
50: - nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()
52: Level: developer
54: .seealso: `DMKSPCreate()`, `DMKSPDestroy()`
55: @*/
56: PetscErrorCode DMKSPCopy(DMKSP kdm, DMKSP nkdm)
57: {
60: nkdm->ops->computeoperators = kdm->ops->computeoperators;
61: nkdm->ops->computerhs = kdm->ops->computerhs;
62: nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
63: nkdm->ops->destroy = kdm->ops->destroy;
64: nkdm->ops->duplicate = kdm->ops->duplicate;
66: nkdm->operatorsctx = kdm->operatorsctx;
67: nkdm->rhsctx = kdm->rhsctx;
68: nkdm->initialguessctx = kdm->initialguessctx;
69: nkdm->data = kdm->data;
70: /* nkdm->originaldm = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */
72: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
73: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
74: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
76: /* implementation specific copy hooks */
77: PetscTryTypeMethod(kdm, duplicate, nkdm);
78: return 0;
79: }
81: /*@C
82: DMGetDMKSP - get read-only private DMKSP context from a DM
84: Logically Collective
86: Input Parameter:
87: . dm - DM to be used with KSP
89: Output Parameter:
90: . snesdm - private DMKSP context
92: Level: developer
94: Notes:
95: Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.
97: .seealso: `DMGetDMKSPWrite()`
98: @*/
99: PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
100: {
102: *kspdm = (DMKSP)dm->dmksp;
103: if (!*kspdm) {
104: PetscInfo(dm, "Creating new DMKSP\n");
105: DMKSPCreate(PetscObjectComm((PetscObject)dm), kspdm);
106: dm->dmksp = (PetscObject)*kspdm;
107: (*kspdm)->originaldm = dm;
108: DMCoarsenHookAdd(dm, DMCoarsenHook_DMKSP, NULL, NULL);
109: DMRefineHookAdd(dm, DMRefineHook_DMKSP, NULL, NULL);
110: }
111: return 0;
112: }
114: /*@C
115: DMGetDMKSPWrite - get write access to private DMKSP context from a DM
117: Logically Collective
119: Input Parameter:
120: . dm - DM to be used with KSP
122: Output Parameter:
123: . kspdm - private DMKSP context
125: Level: developer
127: .seealso: `DMGetDMKSP()`
128: @*/
129: PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
130: {
131: DMKSP kdm;
134: DMGetDMKSP(dm, &kdm);
136: if (kdm->originaldm != dm) { /* Copy on write */
137: DMKSP oldkdm = kdm;
138: PetscInfo(dm, "Copying DMKSP due to write\n");
139: DMKSPCreate(PetscObjectComm((PetscObject)dm), &kdm);
140: DMKSPCopy(oldkdm, kdm);
141: DMKSPDestroy((DMKSP *)&dm->dmksp);
142: dm->dmksp = (PetscObject)kdm;
143: kdm->originaldm = dm;
144: }
145: *kspdm = kdm;
146: return 0;
147: }
149: /*@C
150: DMCopyDMKSP - copies a DM context to a new DM
152: Logically Collective
154: Input Parameters:
155: + dmsrc - DM to obtain context from
156: - dmdest - DM to add context to
158: Level: developer
160: Note:
161: The context is copied by reference. This function does not ensure that a context exists.
163: .seealso: `DMGetDMKSP()`, `KSPSetDM()`
164: @*/
165: PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
166: {
169: DMKSPDestroy((DMKSP *)&dmdest->dmksp);
170: dmdest->dmksp = dmsrc->dmksp;
171: PetscObjectReference(dmdest->dmksp);
172: DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMKSP, NULL, NULL);
173: DMRefineHookAdd(dmdest, DMRefineHook_DMKSP, NULL, NULL);
174: return 0;
175: }
177: /*@C
178: DMKSPSetComputeOperators - set KSP matrix evaluation function
180: Not Collective
182: Input Parameters:
183: + dm - DM to be used with KSP
184: . func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
185: - ctx - context for matrix evaluation
187: Level: advanced
189: Note:
190: KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
191: associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
192: not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
194: .seealso: `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`
195: @*/
196: PetscErrorCode DMKSPSetComputeOperators(DM dm, PetscErrorCode (*func)(KSP, Mat, Mat, void *), void *ctx)
197: {
198: DMKSP kdm;
201: DMGetDMKSPWrite(dm, &kdm);
202: if (func) kdm->ops->computeoperators = func;
203: if (ctx) kdm->operatorsctx = ctx;
204: return 0;
205: }
207: /*@C
208: DMKSPGetComputeOperators - get KSP matrix evaluation function
210: Not Collective
212: Input Parameter:
213: . dm - DM to be used with KSP
215: Output Parameters:
216: + func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
217: - ctx - context for matrix evaluation
219: Level: advanced
221: .seealso: `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`
222: @*/
223: PetscErrorCode DMKSPGetComputeOperators(DM dm, PetscErrorCode (**func)(KSP, Mat, Mat, void *), void *ctx)
224: {
225: DMKSP kdm;
228: DMGetDMKSP(dm, &kdm);
229: if (func) *func = kdm->ops->computeoperators;
230: if (ctx) *(void **)ctx = kdm->operatorsctx;
231: return 0;
232: }
234: /*@C
235: DMKSPSetComputeRHS - set KSP right hand side evaluation function
237: Not Collective
239: Input Parameters:
240: + dm - DM to be used with KSP
241: . func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
242: - ctx - context for right hand side evaluation
244: Level: advanced
246: Note:
247: KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
248: associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
249: not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
251: .seealso: `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
252: @*/
253: PetscErrorCode DMKSPSetComputeRHS(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
254: {
255: DMKSP kdm;
258: DMGetDMKSPWrite(dm, &kdm);
259: if (func) kdm->ops->computerhs = func;
260: if (ctx) kdm->rhsctx = ctx;
261: return 0;
262: }
264: /*@C
265: DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function
267: Not Collective
269: Input Parameters:
270: + dm - DM to be used with KSP
271: . func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
272: - ctx - context for right hand side evaluation
274: Level: advanced
276: Note:
277: KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
278: associated with the DM.
280: .seealso: `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
281: @*/
282: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
283: {
284: DMKSP kdm;
287: DMGetDMKSPWrite(dm, &kdm);
288: if (func) kdm->ops->computeinitialguess = func;
289: if (ctx) kdm->initialguessctx = ctx;
290: return 0;
291: }
293: /*@C
294: DMKSPGetComputeRHS - get KSP right hand side evaluation function
296: Not Collective
298: Input Parameter:
299: . dm - DM to be used with KSP
301: Output Parameters:
302: + func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
303: - ctx - context for right hand side evaluation
305: Level: advanced
307: .seealso: `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
308: @*/
309: PetscErrorCode DMKSPGetComputeRHS(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
310: {
311: DMKSP kdm;
314: DMGetDMKSP(dm, &kdm);
315: if (func) *func = kdm->ops->computerhs;
316: if (ctx) *(void **)ctx = kdm->rhsctx;
317: return 0;
318: }
320: /*@C
321: DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function
323: Not Collective
325: Input Parameter:
326: . dm - DM to be used with KSP
328: Output Parameters:
329: + func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
330: - ctx - context for right hand side evaluation
332: Level: advanced
334: .seealso: `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
335: @*/
336: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
337: {
338: DMKSP kdm;
341: DMGetDMKSP(dm, &kdm);
342: if (func) *func = kdm->ops->computeinitialguess;
343: if (ctx) *(void **)ctx = kdm->initialguessctx;
344: return 0;
345: }