xref: /petsc/src/ksp/ksp/interface/dmksp.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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