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, created with `DMKSPCreate()`
52: Level: developer
54: .seealso: [](chapter_ksp), `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` used with a `KSP`
89: Output Parameter:
90: . snesdm - private `DMKSP` context
92: Level: developer
94: Note:
95: Use `DMGetDMKSPWrite()` if write access is needed. The DMKSPSetXXX API should be used wherever possible.
97: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `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` used with a `KSP`
122: Output Parameter:
123: . kspdm - private `DMKSP` context
125: Level: developer
127: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `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` `DMKSP` 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: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `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: developer
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.
194: Developer Note:
195: If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.
197: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`
198: @*/
199: PetscErrorCode DMKSPSetComputeOperators(DM dm, PetscErrorCode (*func)(KSP, Mat, Mat, void *), void *ctx)
200: {
201: DMKSP kdm;
204: DMGetDMKSPWrite(dm, &kdm);
205: if (func) kdm->ops->computeoperators = func;
206: if (ctx) kdm->operatorsctx = ctx;
207: return 0;
208: }
210: /*@C
211: DMKSPGetComputeOperators - get `KSP` matrix evaluation function
213: Not Collective
215: Input Parameter:
216: . dm - `DM` used with a `KSP`
218: Output Parameters:
219: + func - matrix evaluation function, see `KSPSetComputeOperators()` for calling sequence
220: - ctx - context for matrix evaluation
222: Level: developer
224: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`
225: @*/
226: PetscErrorCode DMKSPGetComputeOperators(DM dm, PetscErrorCode (**func)(KSP, Mat, Mat, void *), void *ctx)
227: {
228: DMKSP kdm;
231: DMGetDMKSP(dm, &kdm);
232: if (func) *func = kdm->ops->computeoperators;
233: if (ctx) *(void **)ctx = kdm->operatorsctx;
234: return 0;
235: }
237: /*@C
238: DMKSPSetComputeRHS - set `KSP` right hand side evaluation function
240: Not Collective
242: Input Parameters:
243: + dm - `DM` used with a `KSP`
244: . func - right hand side evaluation function, see `KSPSetComputeRHS()` for calling sequence
245: - ctx - context for right hand side evaluation
247: Level: developer
249: Note:
250: `KSPSetComputeRHS()` is normally used, but it calls this function internally because the user context is actually
251: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
252: not.
254: Developer Note:
255: If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.
257: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
258: @*/
259: PetscErrorCode DMKSPSetComputeRHS(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
260: {
261: DMKSP kdm;
264: DMGetDMKSPWrite(dm, &kdm);
265: if (func) kdm->ops->computerhs = func;
266: if (ctx) kdm->rhsctx = ctx;
267: return 0;
268: }
270: /*@C
271: DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function
273: Not Collective
275: Input Parameters:
276: + dm - `DM` to be used with `KSP`
277: . func - initial guess evaluation function, see `KSPSetComputeInitialGuess()` for calling sequence
278: - ctx - context for right hand side evaluation
280: Level: developer
282: Note:
283: `KSPSetComputeInitialGuess()` is normally used, but it calls this function internally because the user context is actually
284: associated with the `DM`.
286: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
287: @*/
288: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, PetscErrorCode (*func)(KSP, Vec, void *), void *ctx)
289: {
290: DMKSP kdm;
293: DMGetDMKSPWrite(dm, &kdm);
294: if (func) kdm->ops->computeinitialguess = func;
295: if (ctx) kdm->initialguessctx = ctx;
296: return 0;
297: }
299: /*@C
300: DMKSPGetComputeRHS - get `KSP `right hand side evaluation function
302: Not Collective
304: Input Parameter:
305: . dm - `DM` to be used with `KSP`
307: Output Parameters:
308: + func - right hand side evaluation function, see `KSPSetComputeRHS()` for calling sequence
309: - ctx - context for right hand side evaluation
311: Level: advanced
313: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
314: @*/
315: PetscErrorCode DMKSPGetComputeRHS(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
316: {
317: DMKSP kdm;
320: DMGetDMKSP(dm, &kdm);
321: if (func) *func = kdm->ops->computerhs;
322: if (ctx) *(void **)ctx = kdm->rhsctx;
323: return 0;
324: }
326: /*@C
327: DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function
329: Not Collective
331: Input Parameter:
332: . dm - `DM` used with a `KSP`
334: Output Parameters:
335: + func - initial guess evaluation function, see `KSPSetComputeInitialGuess()` for calling sequence
336: - ctx - context for right hand side evaluation
338: Level: advanced
340: .seealso: [](chapter_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`
341: @*/
342: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, PetscErrorCode (**func)(KSP, Vec, void *), void *ctx)
343: {
344: DMKSP kdm;
347: DMGetDMKSP(dm, &kdm);
348: if (func) *func = kdm->ops->computeinitialguess;
349: if (ctx) *(void **)ctx = kdm->initialguessctx;
350: return 0;
351: }