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, void *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, void *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->computeoperators = kdm->ops->computeoperators;
66: nkdm->ops->computerhs = kdm->ops->computerhs;
67: nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
68: nkdm->ops->destroy = kdm->ops->destroy;
69: nkdm->ops->duplicate = kdm->ops->duplicate;
71: nkdm->operatorsctx = kdm->operatorsctx;
72: nkdm->rhsctx = kdm->rhsctx;
73: nkdm->initialguessctx = kdm->initialguessctx;
74: nkdm->data = kdm->data;
75: /* nkdm->originaldm = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */
77: nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
78: nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
79: nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
81: /* implementation specific copy hooks */
82: PetscTryTypeMethod(kdm, duplicate, nkdm);
83: PetscFunctionReturn(PETSC_SUCCESS);
84: }
86: /*@C
87: DMGetDMKSP - get the read-only private `DMKSP` context from a `DM`
89: Logically Collective
91: Input Parameter:
92: . dm - `DM` used with a `KSP`
94: Output Parameter:
95: . kspdm - private `DMKSP` context
97: Level: developer
99: Note:
100: Use `DMGetDMKSPWrite()` if write access is needed. The DMKSPSetXXX API should be used wherever possible.
102: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSPWrite()`
103: @*/
104: PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
105: {
106: PetscFunctionBegin;
108: *kspdm = (DMKSP)dm->dmksp;
109: if (!*kspdm) {
110: PetscCall(PetscInfo(dm, "Creating new DMKSP\n"));
111: PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), kspdm));
112: dm->dmksp = (PetscObject)*kspdm;
113: (*kspdm)->originaldm = dm;
114: PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMKSP, NULL, NULL));
115: PetscCall(DMRefineHookAdd(dm, DMRefineHook_DMKSP, NULL, NULL));
116: }
117: PetscFunctionReturn(PETSC_SUCCESS);
118: }
120: /*@C
121: DMGetDMKSPWrite - get write access to private `DMKSP` context from a `DM`
123: Logically Collective
125: Input Parameter:
126: . dm - `DM` used with a `KSP`
128: Output Parameter:
129: . kspdm - private `DMKSP` context
131: Level: developer
133: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`
134: @*/
135: PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
136: {
137: DMKSP kdm;
139: PetscFunctionBegin;
141: PetscCall(DMGetDMKSP(dm, &kdm));
142: PetscCheck(kdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMKSP has a NULL originaldm");
143: if (kdm->originaldm != dm) { /* Copy on write */
144: DMKSP oldkdm = kdm;
145: PetscCall(PetscInfo(dm, "Copying DMKSP due to write\n"));
146: PetscCall(DMKSPCreate(PetscObjectComm((PetscObject)dm), &kdm));
147: PetscCall(DMKSPCopy(oldkdm, kdm));
148: PetscCall(DMKSPDestroy((DMKSP *)&dm->dmksp));
149: dm->dmksp = (PetscObject)kdm;
150: kdm->originaldm = dm;
151: }
152: *kspdm = kdm;
153: PetscFunctionReturn(PETSC_SUCCESS);
154: }
156: /*@C
157: DMCopyDMKSP - copies a `DM` `DMKSP` context to a new `DM`
159: Logically Collective
161: Input Parameters:
162: + dmsrc - `DM` to obtain context from
163: - dmdest - `DM` to add context to
165: Level: developer
167: Note:
168: The context is copied by reference. This function does not ensure that a context exists.
170: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`, `KSPSetDM()`
171: @*/
172: PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
173: {
174: PetscFunctionBegin;
177: PetscCall(DMKSPDestroy((DMKSP *)&dmdest->dmksp));
178: dmdest->dmksp = dmsrc->dmksp;
179: PetscCall(PetscObjectReference(dmdest->dmksp));
180: PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMKSP, NULL, NULL));
181: PetscCall(DMRefineHookAdd(dmdest, DMRefineHook_DMKSP, NULL, NULL));
182: PetscFunctionReturn(PETSC_SUCCESS);
183: }
185: /*@C
186: DMKSPSetComputeOperators - set `KSP` matrix evaluation function
188: Not Collective
190: Input Parameters:
191: + dm - `DM` to be used with `KSP`
192: . func - matrix evaluation function, for calling sequence see `KSPComputeOperatorsFn`
193: - ctx - context for matrix evaluation
195: Level: developer
197: Note:
198: `KSPSetComputeOperators()` is normally used, but it calls this function internally because the user context is actually
199: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
200: not.
202: Developer Note:
203: If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.
205: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`, `KSPComputeOperatorsFn`
206: @*/
207: PetscErrorCode DMKSPSetComputeOperators(DM dm, KSPComputeOperatorsFn *func, void *ctx)
208: {
209: DMKSP kdm;
211: PetscFunctionBegin;
213: PetscCall(DMGetDMKSPWrite(dm, &kdm));
214: if (func) kdm->ops->computeoperators = func;
215: if (ctx) kdm->operatorsctx = ctx;
216: PetscFunctionReturn(PETSC_SUCCESS);
217: }
219: /*@C
220: DMKSPGetComputeOperators - get `KSP` matrix evaluation function
222: Not Collective
224: Input Parameter:
225: . dm - `DM` used with a `KSP`
227: Output Parameters:
228: + func - matrix evaluation function, for calling sequence see `KSPComputeOperatorsFn`
229: - ctx - context for matrix evaluation
231: Level: developer
233: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`, `KSPComputeOperatorsFn`
234: @*/
235: PetscErrorCode DMKSPGetComputeOperators(DM dm, KSPComputeOperatorsFn **func, void *ctx)
236: {
237: DMKSP kdm;
239: PetscFunctionBegin;
241: PetscCall(DMGetDMKSP(dm, &kdm));
242: if (func) *func = kdm->ops->computeoperators;
243: if (ctx) *(void **)ctx = kdm->operatorsctx;
244: PetscFunctionReturn(PETSC_SUCCESS);
245: }
247: /*@C
248: DMKSPSetComputeRHS - set `KSP` right hand side evaluation function
250: Not Collective
252: Input Parameters:
253: + dm - `DM` used with a `KSP`
254: . func - right hand side evaluation function, for calling sequence see `KSPComputeRHSFn`
255: - ctx - context for right hand side evaluation
257: Level: developer
259: Note:
260: `KSPSetComputeRHS()` is normally used, but it calls this function internally because the user context is actually
261: associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
262: not.
264: Developer Note:
265: If `DM` took a more central role at some later date, this could become the primary method of setting the matrix.
267: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`
268: @*/
269: PetscErrorCode DMKSPSetComputeRHS(DM dm, KSPComputeRHSFn *func, void *ctx)
270: {
271: DMKSP kdm;
273: PetscFunctionBegin;
275: PetscCall(DMGetDMKSPWrite(dm, &kdm));
276: if (func) kdm->ops->computerhs = func;
277: if (ctx) kdm->rhsctx = ctx;
278: PetscFunctionReturn(PETSC_SUCCESS);
279: }
281: /*@C
282: DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function
284: Not Collective
286: Input Parameters:
287: + dm - `DM` to be used with `KSP`
288: . func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
289: - ctx - context for right hand side evaluation
291: Level: developer
293: Note:
294: `KSPSetComputeInitialGuess()` is normally used, but it calls this function internally because the user context is actually
295: associated with the `DM`.
297: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPSetRHS()`, `KSPComputeInitialGuessFn`
298: @*/
299: PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn *func, void *ctx)
300: {
301: DMKSP kdm;
303: PetscFunctionBegin;
305: PetscCall(DMGetDMKSPWrite(dm, &kdm));
306: if (func) kdm->ops->computeinitialguess = func;
307: if (ctx) kdm->initialguessctx = ctx;
308: PetscFunctionReturn(PETSC_SUCCESS);
309: }
311: /*@C
312: DMKSPGetComputeRHS - get `KSP` right hand side evaluation function
314: Not Collective
316: Input Parameter:
317: . dm - `DM` to be used with `KSP`
319: Output Parameters:
320: + func - right hand side evaluation function, for calling sequence see `KSPComputeRHSFn`
321: - ctx - context for right hand side evaluation
323: Level: advanced
325: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeRHSFn`
326: @*/
327: PetscErrorCode DMKSPGetComputeRHS(DM dm, KSPComputeRHSFn **func, void *ctx)
328: {
329: DMKSP kdm;
331: PetscFunctionBegin;
333: PetscCall(DMGetDMKSP(dm, &kdm));
334: if (func) *func = kdm->ops->computerhs;
335: if (ctx) *(void **)ctx = kdm->rhsctx;
336: PetscFunctionReturn(PETSC_SUCCESS);
337: }
339: /*@C
340: DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function
342: Not Collective
344: Input Parameter:
345: . dm - `DM` used with a `KSP`
347: Output Parameters:
348: + func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
349: - ctx - context for right hand side evaluation
351: Level: advanced
353: .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeInitialGuessFn`
354: @*/
355: PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn **func, void *ctx)
356: {
357: DMKSP kdm;
359: PetscFunctionBegin;
361: PetscCall(DMGetDMKSP(dm, &kdm));
362: if (func) *func = kdm->ops->computeinitialguess;
363: if (ctx) *(void **)ctx = kdm->initialguessctx;
364: PetscFunctionReturn(PETSC_SUCCESS);
365: }