1 #include <petsc/private/dmimpl.h>
2 #include <petsc/private/kspimpl.h> /*I "petscksp.h" I*/
3 #include <petscdm.h>
4
DMKSPDestroy(DMKSP * kdm)5 static PetscErrorCode DMKSPDestroy(DMKSP *kdm)
6 {
7 PetscFunctionBegin;
8 if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
9 PetscValidHeaderSpecific(*kdm, DMKSP_CLASSID, 1);
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 }
18
DMKSPCreate(MPI_Comm comm,DMKSP * kdm)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 }
26
27 /* Attaches the DMKSP to the coarse level.
28 * Under what conditions should we copy versus duplicate?
29 */
DMCoarsenHook_DMKSP(DM dm,DM dmc,PetscCtx ctx)30 static PetscErrorCode DMCoarsenHook_DMKSP(DM dm, DM dmc, PetscCtx ctx)
31 {
32 PetscFunctionBegin;
33 PetscCall(DMCopyDMKSP(dm, dmc));
34 PetscFunctionReturn(PETSC_SUCCESS);
35 }
36
37 /* Attaches the DMKSP to the coarse level.
38 * Under what conditions should we copy versus duplicate?
39 */
DMRefineHook_DMKSP(DM dm,DM dmc,PetscCtx ctx)40 static PetscErrorCode DMRefineHook_DMKSP(DM dm, DM dmc, PetscCtx ctx)
41 {
42 PetscFunctionBegin;
43 PetscCall(DMCopyDMKSP(dm, dmc));
44 PetscFunctionReturn(PETSC_SUCCESS);
45 }
46
47 /*
48 DMKSPCopy - copies the information in a `DMKSP` to another `DMKSP`
49
50 Not Collective
51
52 Input Parameters:
53 + kdm - Original `DMKSP`
54 - nkdm - `DMKSP` to receive the data, created with `DMKSPCreate()`
55
56 Level: developer
57
58 .seealso: [](ch_ksp), `DMKSP`, `DMKSPCreate()`, `DMKSPDestroy()`
59 */
DMKSPCopy(DMKSP kdm,DMKSP nkdm)60 static PetscErrorCode DMKSPCopy(DMKSP kdm, DMKSP nkdm)
61 {
62 PetscFunctionBegin;
63 PetscValidHeaderSpecific(kdm, DMKSP_CLASSID, 1);
64 PetscValidHeaderSpecific(nkdm, DMKSP_CLASSID, 2);
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;
70
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 */
76
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];
80
81 /* implementation specific copy hooks */
82 PetscTryTypeMethod(kdm, duplicate, nkdm);
83 PetscFunctionReturn(PETSC_SUCCESS);
84 }
85
86 /*@C
87 DMGetDMKSP - get the read-only private `DMKSP` context from a `DM`
88
89 Logically Collective
90
91 Input Parameter:
92 . dm - `DM` used with a `KSP`
93
94 Output Parameter:
95 . kspdm - private `DMKSP` context
96
97 Level: developer
98
99 Note:
100 Use `DMGetDMKSPWrite()` if write access is needed. The DMKSPSetXXX API should be used wherever possible.
101
102 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSPWrite()`
103 @*/
DMGetDMKSP(DM dm,DMKSP * kspdm)104 PetscErrorCode DMGetDMKSP(DM dm, DMKSP *kspdm)
105 {
106 PetscFunctionBegin;
107 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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 }
119
120 /*@C
121 DMGetDMKSPWrite - get write access to private `DMKSP` context from a `DM`
122
123 Logically Collective
124
125 Input Parameter:
126 . dm - `DM` used with a `KSP`
127
128 Output Parameter:
129 . kspdm - private `DMKSP` context
130
131 Level: developer
132
133 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`
134 @*/
DMGetDMKSPWrite(DM dm,DMKSP * kspdm)135 PetscErrorCode DMGetDMKSPWrite(DM dm, DMKSP *kspdm)
136 {
137 DMKSP kdm;
138
139 PetscFunctionBegin;
140 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
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 }
155
156 /*@
157 DMCopyDMKSP - copies a `DM` `DMKSP` context to a new `DM`
158
159 Logically Collective
160
161 Input Parameters:
162 + dmsrc - `DM` to obtain context from
163 - dmdest - `DM` to add context to
164
165 Level: developer
166
167 Note:
168 The context is copied by reference. This function does not ensure that a context exists.
169
170 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMGetDMKSP()`, `KSPSetDM()`
171 @*/
DMCopyDMKSP(DM dmsrc,DM dmdest)172 PetscErrorCode DMCopyDMKSP(DM dmsrc, DM dmdest)
173 {
174 PetscFunctionBegin;
175 PetscValidHeaderSpecific(dmsrc, DM_CLASSID, 1);
176 PetscValidHeaderSpecific(dmdest, DM_CLASSID, 2);
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 }
184
185 /*@C
186 DMKSPSetComputeOperators - set `KSP` matrix evaluation function
187
188 Not Collective
189
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
194
195 Level: developer
196
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.
201
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.
204
205 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeOperators()`, `KSPSetOperators()`, `KSPComputeOperatorsFn`
206 @*/
DMKSPSetComputeOperators(DM dm,KSPComputeOperatorsFn * func,PetscCtx ctx)207 PetscErrorCode DMKSPSetComputeOperators(DM dm, KSPComputeOperatorsFn *func, PetscCtx ctx)
208 {
209 DMKSP kdm;
210
211 PetscFunctionBegin;
212 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
213 PetscCall(DMGetDMKSPWrite(dm, &kdm));
214 if (func) kdm->ops->computeoperators = func;
215 if (ctx) kdm->operatorsctx = ctx;
216 PetscFunctionReturn(PETSC_SUCCESS);
217 }
218
219 /*@C
220 DMKSPGetComputeOperators - get `KSP` matrix evaluation function
221
222 Not Collective
223
224 Input Parameter:
225 . dm - `DM` used with a `KSP`
226
227 Output Parameters:
228 + func - matrix evaluation function, for calling sequence see `KSPComputeOperatorsFn`
229 - ctx - context for matrix evaluation
230
231 Level: developer
232
233 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeOperators()`, `DMKSPSetComputeOperators()`, `KSPComputeOperatorsFn`
234 @*/
DMKSPGetComputeOperators(DM dm,KSPComputeOperatorsFn ** func,PetscCtx ctx)235 PetscErrorCode DMKSPGetComputeOperators(DM dm, KSPComputeOperatorsFn **func, PetscCtx ctx)
236 {
237 DMKSP kdm;
238
239 PetscFunctionBegin;
240 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
241 PetscCall(DMGetDMKSP(dm, &kdm));
242 if (func) *func = kdm->ops->computeoperators;
243 if (ctx) *(void **)ctx = kdm->operatorsctx;
244 PetscFunctionReturn(PETSC_SUCCESS);
245 }
246
247 /*@C
248 DMKSPSetComputeRHS - set `KSP` right-hand side evaluation function
249
250 Not Collective
251
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
256
257 Level: developer
258
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.
263
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.
266
267 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`
268 @*/
DMKSPSetComputeRHS(DM dm,KSPComputeRHSFn * func,PetscCtx ctx)269 PetscErrorCode DMKSPSetComputeRHS(DM dm, KSPComputeRHSFn *func, PetscCtx ctx)
270 {
271 DMKSP kdm;
272
273 PetscFunctionBegin;
274 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
275 PetscCall(DMGetDMKSPWrite(dm, &kdm));
276 if (func) kdm->ops->computerhs = func;
277 if (ctx) kdm->rhsctx = ctx;
278 PetscFunctionReturn(PETSC_SUCCESS);
279 }
280
281 /*@C
282 DMKSPSetComputeInitialGuess - set `KSP` initial guess evaluation function
283
284 Not Collective
285
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 initial guess evaluation
290
291 Level: developer
292
293 Note:
294 `KSPSetComputeInitialGuess()` is normally used, but it calls this function internally because the user context is actually
295 associated with the `DM`.
296
297 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `DMKSPGetComputeRHS()`, `KSPComputeInitialGuessFn`
298 @*/
DMKSPSetComputeInitialGuess(DM dm,KSPComputeInitialGuessFn * func,PetscCtx ctx)299 PetscErrorCode DMKSPSetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn *func, PetscCtx ctx)
300 {
301 DMKSP kdm;
302
303 PetscFunctionBegin;
304 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
305 PetscCall(DMGetDMKSPWrite(dm, &kdm));
306 if (func) kdm->ops->computeinitialguess = func;
307 if (ctx) kdm->initialguessctx = ctx;
308 PetscFunctionReturn(PETSC_SUCCESS);
309 }
310
311 /*@C
312 DMKSPGetComputeRHS - get `KSP` right-hand side evaluation function
313
314 Not Collective
315
316 Input Parameter:
317 . dm - `DM` to be used with `KSP`
318
319 Output Parameters:
320 + func - right-hand side evaluation function, for calling sequence see `KSPComputeRHSFn`
321 - ctx - context for right-hand side evaluation
322
323 Level: advanced
324
325 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeRHSFn`
326 @*/
DMKSPGetComputeRHS(DM dm,KSPComputeRHSFn ** func,PetscCtx ctx)327 PetscErrorCode DMKSPGetComputeRHS(DM dm, KSPComputeRHSFn **func, PetscCtx ctx)
328 {
329 DMKSP kdm;
330
331 PetscFunctionBegin;
332 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
333 PetscCall(DMGetDMKSP(dm, &kdm));
334 if (func) *func = kdm->ops->computerhs;
335 if (ctx) *(void **)ctx = kdm->rhsctx;
336 PetscFunctionReturn(PETSC_SUCCESS);
337 }
338
339 /*@C
340 DMKSPGetComputeInitialGuess - get `KSP` initial guess evaluation function
341
342 Not Collective
343
344 Input Parameter:
345 . dm - `DM` used with a `KSP`
346
347 Output Parameters:
348 + func - initial guess evaluation function, for calling sequence see `KSPComputeInitialGuessFn`
349 - ctx - context for right-hand side evaluation
350
351 Level: advanced
352
353 .seealso: [](ch_ksp), `DMKSP`, `DM`, `KSP`, `DMKSPSetContext()`, `KSPSetComputeRHS()`, `DMKSPSetComputeRHS()`, `KSPComputeInitialGuessFn`
354 @*/
DMKSPGetComputeInitialGuess(DM dm,KSPComputeInitialGuessFn ** func,PetscCtx ctx)355 PetscErrorCode DMKSPGetComputeInitialGuess(DM dm, KSPComputeInitialGuessFn **func, PetscCtx ctx)
356 {
357 DMKSP kdm;
358
359 PetscFunctionBegin;
360 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
361 PetscCall(DMGetDMKSP(dm, &kdm));
362 if (func) *func = kdm->ops->computeinitialguess;
363 if (ctx) *(void **)ctx = kdm->initialguessctx;
364 PetscFunctionReturn(PETSC_SUCCESS);
365 }
366