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 PetscErrorCode ierr;
8
9 PetscFunctionBegin;
10 if (!*kdm) PetscFunctionReturn(0);
11 PetscValidHeaderSpecific((*kdm),DMKSP_CLASSID,1);
12 if (--((PetscObject)(*kdm))->refct > 0) {*kdm = NULL; PetscFunctionReturn(0);}
13 if ((*kdm)->ops->destroy) {ierr = ((*kdm)->ops->destroy)(kdm);CHKERRQ(ierr);}
14 ierr = PetscHeaderDestroy(kdm);CHKERRQ(ierr);
15 PetscFunctionReturn(0);
16 }
17
DMKSPCreate(MPI_Comm comm,DMKSP * kdm)18 static PetscErrorCode DMKSPCreate(MPI_Comm comm,DMKSP *kdm)
19 {
20 PetscErrorCode ierr;
21
22 PetscFunctionBegin;
23 ierr = KSPInitializePackage();CHKERRQ(ierr);
24 ierr = PetscHeaderCreate(*kdm, DMKSP_CLASSID, "DMKSP", "DMKSP", "DMKSP", comm, DMKSPDestroy, NULL);CHKERRQ(ierr);
25 PetscFunctionReturn(0);
26 }
27
28
29 /* Attaches the DMKSP to the coarse level.
30 * Under what conditions should we copy versus duplicate?
31 */
DMCoarsenHook_DMKSP(DM dm,DM dmc,void * ctx)32 static PetscErrorCode DMCoarsenHook_DMKSP(DM dm,DM dmc,void *ctx)
33 {
34 PetscErrorCode ierr;
35
36 PetscFunctionBegin;
37 ierr = DMCopyDMKSP(dm,dmc);CHKERRQ(ierr);
38 PetscFunctionReturn(0);
39 }
40
41 /* Attaches the DMKSP to the coarse level.
42 * Under what conditions should we copy versus duplicate?
43 */
DMRefineHook_DMKSP(DM dm,DM dmc,void * ctx)44 static PetscErrorCode DMRefineHook_DMKSP(DM dm,DM dmc,void *ctx)
45 {
46 PetscErrorCode ierr;
47
48 PetscFunctionBegin;
49 ierr = DMCopyDMKSP(dm,dmc);CHKERRQ(ierr);
50 PetscFunctionReturn(0);
51 }
52
53 /*@C
54 DMKSPCopy - copies the information in a DMKSP to another DMKSP
55
56 Not Collective
57
58 Input Argument:
59 + kdm - Original DMKSP
60 - nkdm - DMKSP to receive the data, should have been created with DMKSPCreate()
61
62 Level: developer
63
64 .seealso: DMKSPCreate(), DMKSPDestroy()
65 @*/
DMKSPCopy(DMKSP kdm,DMKSP nkdm)66 PetscErrorCode DMKSPCopy(DMKSP kdm,DMKSP nkdm)
67 {
68 PetscErrorCode ierr;
69
70 PetscFunctionBegin;
71 PetscValidHeaderSpecific(kdm,DMKSP_CLASSID,1);
72 PetscValidHeaderSpecific(nkdm,DMKSP_CLASSID,2);
73 nkdm->ops->computeoperators = kdm->ops->computeoperators;
74 nkdm->ops->computerhs = kdm->ops->computerhs;
75 nkdm->ops->computeinitialguess = kdm->ops->computeinitialguess;
76 nkdm->ops->destroy = kdm->ops->destroy;
77 nkdm->ops->duplicate = kdm->ops->duplicate;
78
79 nkdm->operatorsctx = kdm->operatorsctx;
80 nkdm->rhsctx = kdm->rhsctx;
81 nkdm->initialguessctx = kdm->initialguessctx;
82 nkdm->data = kdm->data;
83 /* nkdm->originaldm = kdm->originaldm; */ /* No need since nkdm->originaldm will be immediately updated in caller DMGetDMKSPWrite */
84
85 nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
86 nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
87 nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
88
89 /* implementation specific copy hooks */
90 if (kdm->ops->duplicate) {ierr = (*kdm->ops->duplicate)(kdm,nkdm);CHKERRQ(ierr);}
91 PetscFunctionReturn(0);
92 }
93
94 /*@C
95 DMGetDMKSP - get read-only private DMKSP context from a DM
96
97 Logically Collective
98
99 Input Argument:
100 . dm - DM to be used with KSP
101
102 Output Argument:
103 . snesdm - private DMKSP context
104
105 Level: developer
106
107 Notes:
108 Use DMGetDMKSPWrite() if write access is needed. The DMKSPSetXXX API should be used wherever possible.
109
110 .seealso: DMGetDMKSPWrite()
111 @*/
DMGetDMKSP(DM dm,DMKSP * kspdm)112 PetscErrorCode DMGetDMKSP(DM dm,DMKSP *kspdm)
113 {
114 PetscErrorCode ierr;
115
116 PetscFunctionBegin;
117 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
118 *kspdm = (DMKSP) dm->dmksp;
119 if (!*kspdm) {
120 ierr = PetscInfo(dm,"Creating new DMKSP\n");CHKERRQ(ierr);
121 ierr = DMKSPCreate(PetscObjectComm((PetscObject)dm),kspdm);CHKERRQ(ierr);
122 dm->dmksp = (PetscObject) *kspdm;
123 (*kspdm)->originaldm = dm;
124 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
125 ierr = DMRefineHookAdd(dm,DMRefineHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
126 }
127 PetscFunctionReturn(0);
128 }
129
130 /*@C
131 DMGetDMKSPWrite - get write access to private DMKSP context from a DM
132
133 Logically Collective
134
135 Input Argument:
136 . dm - DM to be used with KSP
137
138 Output Argument:
139 . kspdm - private DMKSP context
140
141 Level: developer
142
143 .seealso: DMGetDMKSP()
144 @*/
DMGetDMKSPWrite(DM dm,DMKSP * kspdm)145 PetscErrorCode DMGetDMKSPWrite(DM dm,DMKSP *kspdm)
146 {
147 PetscErrorCode ierr;
148 DMKSP kdm;
149
150 PetscFunctionBegin;
151 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
152 ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
153 if (!kdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMKSP has a NULL originaldm");
154 if (kdm->originaldm != dm) { /* Copy on write */
155 DMKSP oldkdm = kdm;
156 ierr = PetscInfo(dm,"Copying DMKSP due to write\n");CHKERRQ(ierr);
157 ierr = DMKSPCreate(PetscObjectComm((PetscObject)dm),&kdm);CHKERRQ(ierr);
158 ierr = DMKSPCopy(oldkdm,kdm);CHKERRQ(ierr);
159 ierr = DMKSPDestroy((DMKSP*)&dm->dmksp);CHKERRQ(ierr);
160 dm->dmksp = (PetscObject)kdm;
161 kdm->originaldm = dm;
162 }
163 *kspdm = kdm;
164 PetscFunctionReturn(0);
165 }
166
167 /*@C
168 DMCopyDMKSP - copies a DM context to a new DM
169
170 Logically Collective
171
172 Input Arguments:
173 + dmsrc - DM to obtain context from
174 - dmdest - DM to add context to
175
176 Level: developer
177
178 Note:
179 The context is copied by reference. This function does not ensure that a context exists.
180
181 .seealso: DMGetDMKSP(), KSPSetDM()
182 @*/
DMCopyDMKSP(DM dmsrc,DM dmdest)183 PetscErrorCode DMCopyDMKSP(DM dmsrc,DM dmdest)
184 {
185 PetscErrorCode ierr;
186
187 PetscFunctionBegin;
188 PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1);
189 PetscValidHeaderSpecific(dmdest,DM_CLASSID,2);
190 ierr = DMKSPDestroy((DMKSP*)&dmdest->dmksp);CHKERRQ(ierr);
191 dmdest->dmksp = dmsrc->dmksp;
192 ierr = PetscObjectReference(dmdest->dmksp);CHKERRQ(ierr);
193 ierr = DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
194 ierr = DMRefineHookAdd(dmdest,DMRefineHook_DMKSP,NULL,NULL);CHKERRQ(ierr);
195 PetscFunctionReturn(0);
196 }
197
198 /*@C
199 DMKSPSetComputeOperators - set KSP matrix evaluation function
200
201 Not Collective
202
203 Input Argument:
204 + dm - DM to be used with KSP
205 . func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
206 - ctx - context for matrix evaluation
207
208 Level: advanced
209
210 Note:
211 KSPSetComputeOperators() is normally used, but it calls this function internally because the user context is actually
212 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
213 not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
214
215 .seealso: DMKSPSetContext(), DMKSPGetComputeOperators(), KSPSetOperators()
216 @*/
DMKSPSetComputeOperators(DM dm,PetscErrorCode (* func)(KSP,Mat,Mat,void *),void * ctx)217 PetscErrorCode DMKSPSetComputeOperators(DM dm,PetscErrorCode (*func)(KSP,Mat,Mat,void*),void *ctx)
218 {
219 PetscErrorCode ierr;
220 DMKSP kdm;
221
222 PetscFunctionBegin;
223 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
224 ierr = DMGetDMKSPWrite(dm,&kdm);CHKERRQ(ierr);
225 if (func) kdm->ops->computeoperators = func;
226 if (ctx) kdm->operatorsctx = ctx;
227 PetscFunctionReturn(0);
228 }
229
230 /*@C
231 DMKSPGetComputeOperators - get KSP matrix evaluation function
232
233 Not Collective
234
235 Input Argument:
236 . dm - DM to be used with KSP
237
238 Output Arguments:
239 + func - matrix evaluation function, see KSPSetComputeOperators() for calling sequence
240 - ctx - context for matrix evaluation
241
242 Level: advanced
243
244 .seealso: DMKSPSetContext(), KSPSetComputeOperators(), DMKSPSetComputeOperators()
245 @*/
DMKSPGetComputeOperators(DM dm,PetscErrorCode (** func)(KSP,Mat,Mat,void *),void * ctx)246 PetscErrorCode DMKSPGetComputeOperators(DM dm,PetscErrorCode (**func)(KSP,Mat,Mat,void*),void *ctx)
247 {
248 PetscErrorCode ierr;
249 DMKSP kdm;
250
251 PetscFunctionBegin;
252 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
253 ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
254 if (func) *func = kdm->ops->computeoperators;
255 if (ctx) *(void**)ctx = kdm->operatorsctx;
256 PetscFunctionReturn(0);
257 }
258
259 /*@C
260 DMKSPSetComputeRHS - set KSP right hand side evaluation function
261
262 Not Collective
263
264 Input Argument:
265 + dm - DM to be used with KSP
266 . func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
267 - ctx - context for right hand side evaluation
268
269 Level: advanced
270
271 Note:
272 KSPSetComputeRHS() is normally used, but it calls this function internally because the user context is actually
273 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or
274 not. If DM took a more central role at some later date, this could become the primary method of setting the matrix.
275
276 .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
277 @*/
DMKSPSetComputeRHS(DM dm,PetscErrorCode (* func)(KSP,Vec,void *),void * ctx)278 PetscErrorCode DMKSPSetComputeRHS(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
279 {
280 PetscErrorCode ierr;
281 DMKSP kdm;
282
283 PetscFunctionBegin;
284 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
285 ierr = DMGetDMKSPWrite(dm,&kdm);CHKERRQ(ierr);
286 if (func) kdm->ops->computerhs = func;
287 if (ctx) kdm->rhsctx = ctx;
288 PetscFunctionReturn(0);
289 }
290
291 /*@C
292 DMKSPSetComputeInitialGuess - set KSP initial guess evaluation function
293
294 Not Collective
295
296 Input Argument:
297 + dm - DM to be used with KSP
298 . func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
299 - ctx - context for right hand side evaluation
300
301 Level: advanced
302
303 Note:
304 KSPSetComputeInitialGuess() is normally used, but it calls this function internally because the user context is actually
305 associated with the DM.
306
307 .seealso: DMKSPSetContext(), DMKSPGetComputeRHS(), KSPSetRHS()
308 @*/
DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (* func)(KSP,Vec,void *),void * ctx)309 PetscErrorCode DMKSPSetComputeInitialGuess(DM dm,PetscErrorCode (*func)(KSP,Vec,void*),void *ctx)
310 {
311 PetscErrorCode ierr;
312 DMKSP kdm;
313
314 PetscFunctionBegin;
315 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
316 ierr = DMGetDMKSPWrite(dm,&kdm);CHKERRQ(ierr);
317 if (func) kdm->ops->computeinitialguess = func;
318 if (ctx) kdm->initialguessctx = ctx;
319 PetscFunctionReturn(0);
320 }
321
322 /*@C
323 DMKSPGetComputeRHS - get KSP right hand side evaluation function
324
325 Not Collective
326
327 Input Argument:
328 . dm - DM to be used with KSP
329
330 Output Arguments:
331 + func - right hand side evaluation function, see KSPSetComputeRHS() for calling sequence
332 - ctx - context for right hand side evaluation
333
334 Level: advanced
335
336 .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
337 @*/
DMKSPGetComputeRHS(DM dm,PetscErrorCode (** func)(KSP,Vec,void *),void * ctx)338 PetscErrorCode DMKSPGetComputeRHS(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
339 {
340 PetscErrorCode ierr;
341 DMKSP kdm;
342
343 PetscFunctionBegin;
344 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
345 ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
346 if (func) *func = kdm->ops->computerhs;
347 if (ctx) *(void**)ctx = kdm->rhsctx;
348 PetscFunctionReturn(0);
349 }
350
351 /*@C
352 DMKSPGetComputeInitialGuess - get KSP initial guess evaluation function
353
354 Not Collective
355
356 Input Argument:
357 . dm - DM to be used with KSP
358
359 Output Arguments:
360 + func - initial guess evaluation function, see KSPSetComputeInitialGuess() for calling sequence
361 - ctx - context for right hand side evaluation
362
363 Level: advanced
364
365 .seealso: DMKSPSetContext(), KSPSetComputeRHS(), DMKSPSetComputeRHS()
366 @*/
DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (** func)(KSP,Vec,void *),void * ctx)367 PetscErrorCode DMKSPGetComputeInitialGuess(DM dm,PetscErrorCode (**func)(KSP,Vec,void*),void *ctx)
368 {
369 PetscErrorCode ierr;
370 DMKSP kdm;
371
372 PetscFunctionBegin;
373 PetscValidHeaderSpecific(dm,DM_CLASSID,1);
374 ierr = DMGetDMKSP(dm,&kdm);CHKERRQ(ierr);
375 if (func) *func = kdm->ops->computeinitialguess;
376 if (ctx) *(void**)ctx = kdm->initialguessctx;
377 PetscFunctionReturn(0);
378 }
379