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: PetscFunctionBegin;
8: if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
10: if (--((PetscObject)*kdm)->refct > 0) {
11: *kdm = NULL;
12: PetscFunctionReturn(PETSC_SUCCESS);
13: }
14: if ((*kdm)->ops->destroy) PetscCall(((*kdm)->ops->destroy)(kdm));
15: PetscCall(PetscHeaderDestroy(kdm));
16: PetscFunctionReturn(PETSC_SUCCESS);
17: }
19: static PetscErrorCode DMKSPCreate(MPI_Comm comm, DMKSP *kdm)
20: {
21: PetscFunctionBegin;
22: PetscCall(KSPInitializePackage());
23: PetscCall(PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL));
24: PetscFunctionReturn(PETSC_SUCCESS);
25: }
27: /* Attaches the DMKSP to the coarse level.
28: * Under what conditions should we copy versus duplicate?
29: */
30: static PetscErrorCode DMCoarsenHook_DMKSP(DM dm, DM dmc, PetscCtx ctx)
31: {
32: PetscFunctionBegin;
33: PetscCall(DMCopyDMKSP(dm, dmc));
34: PetscFunctionReturn(PETSC_SUCCESS);
35: }
37: /* Attaches the DMKSP to the coarse level.
38: * Under what conditions should we copy versus duplicate?
39: */
40: static PetscErrorCode DMRefineHook_DMKSP(DM dm, DM dmc, PetscCtx ctx)
41: {
42: PetscFunctionBegin;
43: PetscCall(DMCopyDMKSP(dm, dmc));
44: PetscFunctionReturn(PETSC_SUCCESS);
45: }
47: /*
48: DMKSPCopy - copies the information in a `DMKSP` to another `DMKSP`
50: Not Collective
52: Input Parameters:
53: + kdm - Original `DMKSP`
54: - nkdm - `DMKSP` to receive the data, created with `DMKSPCreate()`
56: Level: developer
58: .seealso: [](ch_ksp), `DMKSP`, `DMKSPCreate()`, `DMKSPDestroy()`
59: */
60: static PetscErrorCode DMKSPCopy(DMKSP kdm, DMKSP nkdm)
61: {
62: PetscFunctionBegin;
65: nkdm->ops->createoperators = kdm->ops->createoperators;
66: nkdm->ops->computeoperators = kdm->ops->computeoperators;
67: nkdm->ops->computerhs = kdm->ops->computerhs;
68: nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
69: nkdm->ops->destroy = kdm->ops->destroy;
70: nkdm->ops->duplicate = kdm->ops->duplicate;
72: nkdm->createoperatorsctx = kdm->createoperatorsctx;
73: nkdm->operatorsctx = kdm->operatorsctx;
74: nkdm->rhsctx = kdm->rhsctx;
75: nkdm->initialguessctx = kdm->initialguessctx;
76: nkdm->data = kdm->data;
77: /* nkdm->originaldm = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */
79: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
80: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
81: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
83: /* implementation specific copy hooks */
84: PetscTryTypeMethod(kdm, duplicate, nkdm);
85: PetscFunctionReturn(PETSC_SUCCESS);
86: }
88: /*@
89: DMGetDMKSP - get the read-only private `DMKSP` context from a `DM`
91: Logically Collective
93: Input Parameter:
94: . dm - `DM` used with a `KSP`
96: Output Parameter:
97: . kspdm - private `DMKSP` context
99: Level: developer
101: Note:
102: Use `DMGetDMKSPWrite()` if write access is needed. The DMKSPSetXXX API should be used wherever possible.
104: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSPWrite()`
105: @*/
106: PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
107: {
108: PetscFunctionBegin;
110: *kspdm = (DMKSP)dm->dmksp;
111: if (!*kspdm) {
112: PetscCall(PetscInfo(dm, "Creating new DMKSP\n"));
113: PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), kspdm));
114: dm->dmksp = (PetscObject)*kspdm;
115: (*kspdm)->originaldm = dm;
116: PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMKSP, NULL, NULL));
117: PetscCall(DMRefineHookAdd(dm, DMRefineHook_DMKSP, NULL, NULL));
118: }
119: PetscFunctionReturn(PETSC_SUCCESS);
120: }
122: /*@
123: DMGetDMKSPWrite - get write access to private `DMKSP` context from a `DM`
125: Logically Collective
127: Input Parameter:
128: . dm - `DM` used with a `KSP`
130: Output Parameter:
131: . kspdm - private `DMKSP` context
133: Level: developer
135: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`
136: @*/
137: PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
138: {
139: DMKSP kdm;
141: PetscFunctionBegin;
143: PetscCall(DMGetDMKSP(dm, &kdm));
144: PetscCheck(kdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMKSP has a NULL originaldm");
145: if (kdm->originaldm != dm) { /* Copy on write */
146: DMKSP oldkdm = kdm;
147: PetscCall(PetscInfo(dm, "Copying DMKSP due to write\n"));
148: PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), &kdm));
149: PetscCall(DMKSPCopy(oldkdm, kdm));
150: PetscCall(DMKSPDestroy((DMKSP *)&dm->dmksp));
151: dm->dmksp = (PetscObject)kdm;
152: kdm->originaldm = dm;
153: }
154: *kspdm = kdm;
155: PetscFunctionReturn(PETSC_SUCCESS);
156: }
158: /*@
159: DMCopyDMKSP - copies a `DM` `DMKSP` context to a new `DM`
161: Logically Collective
163: Input Parameters:
164: + dmsrc - `DM` to obtain context from
165: - dmdest - `DM` to add context to
167: Level: developer
169: Note:
170: The context is copied by reference. This function does not ensure that a context exists.
172: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`, `KSPSetDM()`
173: @*/
174: PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
175: {
176: PetscFunctionBegin;
179: PetscCall(DMKSPDestroy((DMKSP *)&dmdest->dmksp));
180: dmdest->dmksp = dmsrc->dmksp;
181: PetscCall(PetscObjectReference(dmdest->dmksp));
182: PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMKSP, NULL, NULL));
183: PetscCall(DMRefineHookAdd(dmdest, DMRefineHook_DMKSP, NULL, NULL));
184: PetscFunctionReturn(PETSC_SUCCESS);
185: }
187: /*@
188: DMKSPSetCreateOperators - set the `KSP` matrix creation function used in `KSPSetUp()`
190: Logically Collective
192: Input Parameters:
193: + dm - `DM` to be used with `KSP`
194: . func - matrix creation function, for calling sequence see `KSPCreateOperatorsFn`
195: - ctx - context for matrix creation
197: Level: developer
199: Notes:
200: `func` is called by `KSPSetUp()` when `KSPSetDMActive()` has enabled the `KSP_DMACTIVE_OPERATOR` flag.
201: It is used to create once the matrices before the matrix evaluation function set with `DMKSPSetComputeOperators()` is called.
202: Pass `NULL` for both `func` and `ctx` to remove the callback.
204: If this matrix creation function is not provided, `KSPSetUp()` will create a single matrix `A` (also used for `P`) using `DMCreateMatrix()`.
206: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPGetCreateOperators()`, `DMKSPSetComputeOperators()`, `KSPCreateOperatorsFn`, `KSPSetDMActive()`, `KSPSetOperators()`, `DMCreateMatrix()`
207: @*/
208: PetscErrorCode DMKSPSetCreateOperators(DM dm, KSPCreateOperatorsFn *func, PetscCtx ctx)
209: {
210: DMKSP kdm;
212: PetscFunctionBegin;
214: PetscCall(DMGetDMKSPWrite(dm, &kdm));
215: if (func) kdm->ops->createoperators = func;
216: if (ctx) kdm->createoperatorsctx = ctx;
217: if (!func && !ctx) {
218: kdm->ops->createoperators = NULL;
219: kdm->createoperatorsctx = NULL;
220: }
221: PetscFunctionReturn(PETSC_SUCCESS);
222: }
224: /*@
225: DMKSPGetCreateOperators - get `KSP` matrix creation function
227: Not Collective
229: Input Parameter:
230: . dm - `DM` used with a `KSP`
232: Output Parameters:
233: + func - matrix creation function, for calling sequence see `KSPCreateOperatorsFn`
234: - ctx - context for matrix creation
236: Level: developer
238: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetCreateOperators()`, `DMKSPSetComputeOperators()`, `KSPCreateOperatorsFn`
239: @*/
240: PetscErrorCode DMKSPGetCreateOperators(DM dm, KSPCreateOperatorsFn **func, PetscCtx ctx)
241: {
242: DMKSP kdm;
244: PetscFunctionBegin;
246: PetscCall(DMGetDMKSP(dm, &kdm));
247: if (func) *func = kdm->ops->createoperators;
248: if (ctx) *(void **)ctx = kdm->createoperatorsctx;
249: PetscFunctionReturn(PETSC_SUCCESS);
250: }
252: /*@
253: DMKSPSetComputeOperators - set `KSP` matrix evaluation function
255: Logically Collective
257: Input Parameters:
258: + dm - `DM` to be used with `KSP`
259: . func - matrix evaluation function, for calling sequence see `KSPComputeOperatorsFn`
260: - ctx - context for matrix evaluation
262: Level: developer
264: Note:
265: `KSPSetComputeOperators()` is normally used, but it calls this function internally because the application context is actually
266: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
267: not.
269: Developer Note:
270: If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.
272: Pass `NULL` for both `func` and `ctx` to remove the callback.
274: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`, `KSPComputeOperatorsFn`
275: @*/
276: PetscErrorCode DMKSPSetComputeOperators(DM dm, KSPComputeOperatorsFn *func, PetscCtx ctx)
277: {
278: DMKSP kdm;
280: PetscFunctionBegin;
282: PetscCall(DMGetDMKSPWrite(dm, &kdm));
283: if (func) kdm->ops->computeoperators = func;
284: if (ctx) kdm->operatorsctx = ctx;
285: if (!func && !ctx) {
286: kdm->ops->computeoperators = NULL;
287: kdm->operatorsctx = NULL;
288: }
289: PetscFunctionReturn(PETSC_SUCCESS);
290: }
292: /*@
293: DMKSPGetComputeOperators - get `KSP` matrix evaluation function
295: Not Collective
297: Input Parameter:
298: . dm - `DM` used with a `KSP`
300: Output Parameters:
301: + func - matrix evaluation function, for calling sequence see `KSPComputeOperatorsFn`
302: - ctx - context for matrix evaluation
304: Level: developer
306: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`, `KSPComputeOperatorsFn`
307: @*/
308: PetscErrorCode DMKSPGetComputeOperators(DM dm, KSPComputeOperatorsFn **func, PetscCtx ctx)
309: {
310: DMKSP kdm;
312: PetscFunctionBegin;
314: PetscCall(DMGetDMKSP(dm, &kdm));
315: if (func) *func = kdm->ops->computeoperators;
316: if (ctx) *(void **)ctx = kdm->operatorsctx;
317: PetscFunctionReturn(PETSC_SUCCESS);
318: }
320: /*@
321: DMKSPSetComputeRHS - set `KSP` right-hand side evaluation function
323: Not Collective
325: Input Parameters:
326: + dm - `DM` used with a `KSP`
327: . func - right-hand side evaluation function, for calling sequence see `KSPComputeRHSFn`
328: - ctx - context for right-hand side evaluation
330: Level: developer
332: Note:
333: `KSPSetComputeRHS()` is normally used, but it calls this function internally because the application context is actually
334: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
335: not.
337: Developer Note:
338: If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.
340: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`
341: @*/
342: PetscErrorCode DMKSPSetComputeRHS(DM dm, KSPComputeRHSFn *func, PetscCtx ctx)
343: {
344: DMKSP kdm;
346: PetscFunctionBegin;
348: PetscCall(DMGetDMKSPWrite(dm, &kdm));
349: if (func) kdm->ops->computerhs = func;
350: if (ctx) kdm->rhsctx = ctx;
351: PetscFunctionReturn(PETSC_SUCCESS);
352: }
354: /*@
355: DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function
357: Not Collective
359: Input Parameters:
360: + dm - `DM` to be used with `KSP`
361: . func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
362: - ctx - context for initial guess evaluation
364: Level: developer
366: Note:
367: `KSPSetComputeInitialGuess()` is normally used, but it calls this function internally because the application context is actually
368: associated with the `DM`.
370: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPComputeInitialGuessFn`
371: @*/
372: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn *func, PetscCtx ctx)
373: {
374: DMKSP kdm;
376: PetscFunctionBegin;
378: PetscCall(DMGetDMKSPWrite(dm, &kdm));
379: if (func) kdm->ops->computeinitialguess = func;
380: if (ctx) kdm->initialguessctx = ctx;
381: PetscFunctionReturn(PETSC_SUCCESS);
382: }
384: /*@
385: DMKSPGetComputeRHS - get `KSP` right-hand side evaluation function
387: Not Collective
389: Input Parameter:
390: . dm - `DM` to be used with `KSP`
392: Output Parameters:
393: + func - right-hand side evaluation function, for calling sequence see `KSPComputeRHSFn`
394: - ctx - context for right-hand side evaluation
396: Level: advanced
398: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeRHSFn`
399: @*/
400: PetscErrorCode DMKSPGetComputeRHS(DM dm, KSPComputeRHSFn **func, PetscCtx ctx)
401: {
402: DMKSP kdm;
404: PetscFunctionBegin;
406: PetscCall(DMGetDMKSP(dm, &kdm));
407: if (func) *func = kdm->ops->computerhs;
408: if (ctx) *(void **)ctx = kdm->rhsctx;
409: PetscFunctionReturn(PETSC_SUCCESS);
410: }
412: /*@
413: DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function
415: Not Collective
417: Input Parameter:
418: . dm - `DM` used with a `KSP`
420: Output Parameters:
421: + func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
422: - ctx - context for right-hand side evaluation
424: Level: advanced
426: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeInitialGuessFn`
427: @*/
428: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn **func, PetscCtx ctx)
429: {
430: DMKSP kdm;
432: PetscFunctionBegin;
434: PetscCall(DMGetDMKSP(dm, &kdm));
435: if (func) *func = kdm->ops->computeinitialguess;
436: if (ctx) *(void **)ctx = kdm->initialguessctx;
437: PetscFunctionReturn(PETSC_SUCCESS);
438: }