1 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/
2 #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
3
DMSNESUnsetFunctionContext_DMSNES(DMSNES sdm)4 static PetscErrorCode DMSNESUnsetFunctionContext_DMSNES(DMSNES sdm)
5 {
6 PetscFunctionBegin;
7 PetscCall(PetscObjectCompose((PetscObject)sdm, "function ctx", NULL));
8 sdm->functionctxcontainer = NULL;
9 PetscFunctionReturn(PETSC_SUCCESS);
10 }
11
DMSNESUnsetJacobianContext_DMSNES(DMSNES sdm)12 static PetscErrorCode DMSNESUnsetJacobianContext_DMSNES(DMSNES sdm)
13 {
14 PetscFunctionBegin;
15 PetscCall(PetscObjectCompose((PetscObject)sdm, "jacobian ctx", NULL));
16 sdm->jacobianctxcontainer = NULL;
17 PetscFunctionReturn(PETSC_SUCCESS);
18 }
19
DMSNESDestroy(DMSNES * kdm)20 static PetscErrorCode DMSNESDestroy(DMSNES *kdm)
21 {
22 PetscFunctionBegin;
23 if (!*kdm) PetscFunctionReturn(PETSC_SUCCESS);
24 PetscValidHeaderSpecific(*kdm, DMSNES_CLASSID, 1);
25 if (--((PetscObject)*kdm)->refct > 0) {
26 *kdm = NULL;
27 PetscFunctionReturn(PETSC_SUCCESS);
28 }
29 PetscCall(DMSNESUnsetFunctionContext_DMSNES(*kdm));
30 PetscCall(DMSNESUnsetJacobianContext_DMSNES(*kdm));
31 PetscTryTypeMethod(*kdm, destroy);
32 PetscCall(PetscHeaderDestroy(kdm));
33 PetscFunctionReturn(PETSC_SUCCESS);
34 }
35
DMSNESLoad(DMSNES kdm,PetscViewer viewer)36 PetscErrorCode DMSNESLoad(DMSNES kdm, PetscViewer viewer)
37 {
38 PetscFunctionBegin;
39 PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->computefunction, 1, NULL, PETSC_FUNCTION));
40 PetscCall(PetscViewerBinaryRead(viewer, &kdm->ops->computejacobian, 1, NULL, PETSC_FUNCTION));
41 PetscFunctionReturn(PETSC_SUCCESS);
42 }
43
DMSNESView(DMSNES kdm,PetscViewer viewer)44 PetscErrorCode DMSNESView(DMSNES kdm, PetscViewer viewer)
45 {
46 PetscBool isascii, isbinary;
47
48 PetscFunctionBegin;
49 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
50 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
51 if (isascii) {
52 #if defined(PETSC_SERIALIZE_FUNCTIONS)
53 const char *fname;
54
55 PetscCall(PetscFPTFind(kdm->ops->computefunction, &fname));
56 if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, "Function used by SNES: %s\n", fname));
57 PetscCall(PetscFPTFind(kdm->ops->computejacobian, &fname));
58 if (fname) PetscCall(PetscViewerASCIIPrintf(viewer, "Jacobian function used by SNES: %s\n", fname));
59 #endif
60 } else if (isbinary) {
61 struct {
62 SNESFunctionFn *func;
63 } funcstruct;
64 struct {
65 SNESJacobianFn *jac;
66 } jacstruct;
67 funcstruct.func = kdm->ops->computefunction;
68 jacstruct.jac = kdm->ops->computejacobian;
69 PetscCall(PetscViewerBinaryWrite(viewer, &funcstruct, 1, PETSC_FUNCTION));
70 PetscCall(PetscViewerBinaryWrite(viewer, &jacstruct, 1, PETSC_FUNCTION));
71 }
72 PetscFunctionReturn(PETSC_SUCCESS);
73 }
74
DMSNESCreate(MPI_Comm comm,DMSNES * kdm)75 static PetscErrorCode DMSNESCreate(MPI_Comm comm, DMSNES *kdm)
76 {
77 PetscFunctionBegin;
78 PetscCall(SNESInitializePackage());
79 PetscCall(PetscHeaderCreate(*kdm, DMSNES_CLASSID, "DMSNES", "DMSNES", "DMSNES", comm, DMSNESDestroy, DMSNESView));
80 PetscFunctionReturn(PETSC_SUCCESS);
81 }
82
83 /* Attaches the DMSNES to the coarse level.
84 * Under what conditions should we copy versus duplicate?
85 */
DMCoarsenHook_DMSNES(DM dm,DM dmc,PetscCtx ctx)86 static PetscErrorCode DMCoarsenHook_DMSNES(DM dm, DM dmc, PetscCtx ctx)
87 {
88 PetscFunctionBegin;
89 PetscCall(DMCopyDMSNES(dm, dmc));
90 PetscFunctionReturn(PETSC_SUCCESS);
91 }
92
93 /* This could restrict auxiliary information to the coarse level.
94 */
DMRestrictHook_DMSNES(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,PetscCtx ctx)95 static PetscErrorCode DMRestrictHook_DMSNES(DM dm, Mat Restrict, Vec rscale, Mat Inject, DM dmc, PetscCtx ctx)
96 {
97 PetscFunctionBegin;
98 PetscFunctionReturn(PETSC_SUCCESS);
99 }
100
101 /* Attaches the DMSNES to the subdomain. */
DMSubDomainHook_DMSNES(DM dm,DM subdm,PetscCtx ctx)102 static PetscErrorCode DMSubDomainHook_DMSNES(DM dm, DM subdm, PetscCtx ctx)
103 {
104 PetscFunctionBegin;
105 PetscCall(DMCopyDMSNES(dm, subdm));
106 PetscFunctionReturn(PETSC_SUCCESS);
107 }
108
109 /* This could restrict auxiliary information to the coarse level.
110 */
DMSubDomainRestrictHook_DMSNES(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,PetscCtx ctx)111 static PetscErrorCode DMSubDomainRestrictHook_DMSNES(DM dm, VecScatter gscat, VecScatter lscat, DM subdm, PetscCtx ctx)
112 {
113 PetscFunctionBegin;
114 PetscFunctionReturn(PETSC_SUCCESS);
115 }
116
DMRefineHook_DMSNES(DM dm,DM dmf,PetscCtx ctx)117 static PetscErrorCode DMRefineHook_DMSNES(DM dm, DM dmf, PetscCtx ctx)
118 {
119 PetscFunctionBegin;
120 PetscCall(DMCopyDMSNES(dm, dmf));
121 PetscFunctionReturn(PETSC_SUCCESS);
122 }
123
124 /* This could restrict auxiliary information to the coarse level.
125 */
DMInterpolateHook_DMSNES(DM dm,Mat Interp,DM dmf,PetscCtx ctx)126 static PetscErrorCode DMInterpolateHook_DMSNES(DM dm, Mat Interp, DM dmf, PetscCtx ctx)
127 {
128 PetscFunctionBegin;
129 PetscFunctionReturn(PETSC_SUCCESS);
130 }
131
132 /*
133 DMSNESCopy - copies the information in a `DMSNES` to another `DMSNES`
134
135 Not Collective
136
137 Input Parameters:
138 + kdm - Original `DMSNES`
139 - nkdm - `DMSNES` to receive the data, should have been created with `DMSNESCreate()`
140
141 Level: developer
142
143 .seealso: [](ch_snes), `DMSNES`, `DMSNESCreate()`, `DMSNESDestroy()`
144 */
DMSNESCopy(DMSNES kdm,DMSNES nkdm)145 static PetscErrorCode DMSNESCopy(DMSNES kdm, DMSNES nkdm)
146 {
147 PetscFunctionBegin;
148 PetscValidHeaderSpecific(kdm, DMSNES_CLASSID, 1);
149 PetscValidHeaderSpecific(nkdm, DMSNES_CLASSID, 2);
150 nkdm->ops->computefunction = kdm->ops->computefunction;
151 nkdm->ops->computejacobian = kdm->ops->computejacobian;
152 nkdm->ops->computegs = kdm->ops->computegs;
153 nkdm->ops->computeobjective = kdm->ops->computeobjective;
154 nkdm->ops->computepjacobian = kdm->ops->computepjacobian;
155 nkdm->ops->computepfunction = kdm->ops->computepfunction;
156 nkdm->ops->destroy = kdm->ops->destroy;
157 nkdm->ops->duplicate = kdm->ops->duplicate;
158
159 nkdm->gsctx = kdm->gsctx;
160 nkdm->pctx = kdm->pctx;
161 nkdm->objectivectx = kdm->objectivectx;
162 nkdm->originaldm = kdm->originaldm;
163 nkdm->functionctxcontainer = kdm->functionctxcontainer;
164 nkdm->jacobianctxcontainer = kdm->jacobianctxcontainer;
165 if (nkdm->functionctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "function ctx", (PetscObject)nkdm->functionctxcontainer));
166 if (nkdm->jacobianctxcontainer) PetscCall(PetscObjectCompose((PetscObject)nkdm, "jacobian ctx", (PetscObject)nkdm->jacobianctxcontainer));
167
168 /*
169 nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
170 nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
171 nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
172 */
173
174 /* implementation specific copy hooks */
175 PetscTryTypeMethod(kdm, duplicate, nkdm);
176 PetscFunctionReturn(PETSC_SUCCESS);
177 }
178
179 /*@C
180 DMGetDMSNES - get read-only private `DMSNES` context from a `DM`
181
182 Not Collective
183
184 Input Parameter:
185 . dm - `DM` to be used with `SNES`
186
187 Output Parameter:
188 . snesdm - private `DMSNES` context
189
190 Level: developer
191
192 Note:
193 Use `DMGetDMSNESWrite()` if write access is needed. The DMSNESSetXXX API should be used wherever possible.
194
195 .seealso: [](ch_snes), `DMSNES`, `DMGetDMSNESWrite()`
196 @*/
DMGetDMSNES(DM dm,DMSNES * snesdm)197 PetscErrorCode DMGetDMSNES(DM dm, DMSNES *snesdm)
198 {
199 PetscFunctionBegin;
200 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
201 *snesdm = (DMSNES)dm->dmsnes;
202 if (!*snesdm) {
203 PetscCall(PetscInfo(dm, "Creating new DMSNES\n"));
204 PetscCall(DMSNESCreate(PetscObjectComm((PetscObject)dm), snesdm));
205
206 dm->dmsnes = (PetscObject)*snesdm;
207 (*snesdm)->originaldm = dm;
208 PetscCall(DMCoarsenHookAdd(dm, DMCoarsenHook_DMSNES, DMRestrictHook_DMSNES, NULL));
209 PetscCall(DMRefineHookAdd(dm, DMRefineHook_DMSNES, DMInterpolateHook_DMSNES, NULL));
210 PetscCall(DMSubDomainHookAdd(dm, DMSubDomainHook_DMSNES, DMSubDomainRestrictHook_DMSNES, NULL));
211 }
212 PetscFunctionReturn(PETSC_SUCCESS);
213 }
214
215 /*@C
216 DMGetDMSNESWrite - get write access to private `DMSNES` context from a `DM`
217
218 Not Collective
219
220 Input Parameter:
221 . dm - `DM` to be used with `SNES`
222
223 Output Parameter:
224 . snesdm - private `DMSNES` context
225
226 Level: developer
227
228 .seealso: [](ch_snes), `DMSNES`, `DMGetDMSNES()`
229 @*/
DMGetDMSNESWrite(DM dm,DMSNES * snesdm)230 PetscErrorCode DMGetDMSNESWrite(DM dm, DMSNES *snesdm)
231 {
232 DMSNES sdm;
233
234 PetscFunctionBegin;
235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
236 PetscCall(DMGetDMSNES(dm, &sdm));
237 PetscCheck(sdm->originaldm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DMSNES has a NULL originaldm");
238 if (sdm->originaldm != dm) { /* Copy on write */
239 DMSNES oldsdm = sdm;
240 PetscCall(PetscInfo(dm, "Copying DMSNES due to write\n"));
241 PetscCall(DMSNESCreate(PetscObjectComm((PetscObject)dm), &sdm));
242 PetscCall(DMSNESCopy(oldsdm, sdm));
243 PetscCall(DMSNESDestroy((DMSNES *)&dm->dmsnes));
244 dm->dmsnes = (PetscObject)sdm;
245 sdm->originaldm = dm;
246 }
247 *snesdm = sdm;
248 PetscFunctionReturn(PETSC_SUCCESS);
249 }
250
251 /*@
252 DMCopyDMSNES - copies a `DMSNES` context to a new `DM`
253
254 Logically Collective
255
256 Input Parameters:
257 + dmsrc - `DM` to obtain context from
258 - dmdest - `DM` to add context to
259
260 Level: developer
261
262 Note:
263 The context is copied by reference. This function does not ensure that a context exists.
264
265 .seealso: [](ch_snes), `DMSNES`, `DMGetDMSNES()`, `SNESSetDM()`
266 @*/
DMCopyDMSNES(DM dmsrc,DM dmdest)267 PetscErrorCode DMCopyDMSNES(DM dmsrc, DM dmdest)
268 {
269 PetscFunctionBegin;
270 PetscValidHeaderSpecific(dmsrc, DM_CLASSID, 1);
271 PetscValidHeaderSpecific(dmdest, DM_CLASSID, 2);
272 if (!dmdest->dmsnes) PetscCall(DMSNESCreate(PetscObjectComm((PetscObject)dmdest), (DMSNES *)&dmdest->dmsnes));
273 PetscCall(DMSNESCopy((DMSNES)dmsrc->dmsnes, (DMSNES)dmdest->dmsnes));
274 PetscCall(DMCoarsenHookAdd(dmdest, DMCoarsenHook_DMSNES, NULL, NULL));
275 PetscCall(DMRefineHookAdd(dmdest, DMRefineHook_DMSNES, NULL, NULL));
276 PetscCall(DMSubDomainHookAdd(dmdest, DMSubDomainHook_DMSNES, DMSubDomainRestrictHook_DMSNES, NULL));
277 PetscFunctionReturn(PETSC_SUCCESS);
278 }
279
280 /*@C
281 DMSNESSetFunction - set `SNES` residual evaluation function
282
283 Not Collective
284
285 Input Parameters:
286 + dm - DM to be used with `SNES`
287 . f - residual evaluation function; see `SNESFunctionFn` for calling sequence
288 - ctx - context for residual evaluation
289
290 Level: developer
291
292 Note:
293 `SNESSetFunction()` is normally used, but it calls this function internally because the user context is actually
294 associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
295 not.
296
297 Developer Note:
298 If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
299
300 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `SNESFunctionFn`
301 @*/
DMSNESSetFunction(DM dm,SNESFunctionFn * f,PetscCtx ctx)302 PetscErrorCode DMSNESSetFunction(DM dm, SNESFunctionFn *f, PetscCtx ctx)
303 {
304 DMSNES sdm;
305
306 PetscFunctionBegin;
307 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
308 PetscCall(DMGetDMSNESWrite(dm, &sdm));
309 if (f) sdm->ops->computefunction = f;
310 if (ctx) {
311 PetscContainer ctxcontainer;
312 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)sdm), &ctxcontainer));
313 PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
314 PetscCall(PetscObjectCompose((PetscObject)sdm, "function ctx", (PetscObject)ctxcontainer));
315 sdm->functionctxcontainer = ctxcontainer;
316 PetscCall(PetscContainerDestroy(&ctxcontainer));
317 }
318 PetscFunctionReturn(PETSC_SUCCESS);
319 }
320
321 /*@C
322 DMSNESSetFunctionContextDestroy - set `SNES` residual evaluation context destroy function
323
324 Not Collective
325
326 Input Parameters:
327 + dm - `DM` to be used with `SNES`
328 - f - residual evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
329
330 Level: developer
331
332 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetFunction()`, `SNESSetFunction()`, `PetscCtxDestroyFn`
333 @*/
DMSNESSetFunctionContextDestroy(DM dm,PetscCtxDestroyFn * f)334 PetscErrorCode DMSNESSetFunctionContextDestroy(DM dm, PetscCtxDestroyFn *f)
335 {
336 DMSNES sdm;
337
338 PetscFunctionBegin;
339 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
340 PetscCall(DMGetDMSNESWrite(dm, &sdm));
341 if (sdm->functionctxcontainer) PetscCall(PetscContainerSetCtxDestroy(sdm->functionctxcontainer, f));
342 PetscFunctionReturn(PETSC_SUCCESS);
343 }
344
DMSNESUnsetFunctionContext_Internal(DM dm)345 PetscErrorCode DMSNESUnsetFunctionContext_Internal(DM dm)
346 {
347 DMSNES sdm;
348
349 PetscFunctionBegin;
350 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
351 PetscCall(DMGetDMSNESWrite(dm, &sdm));
352 PetscCall(DMSNESUnsetFunctionContext_DMSNES(sdm));
353 PetscFunctionReturn(PETSC_SUCCESS);
354 }
355
356 /*@C
357 DMSNESSetMFFunction - set `SNES` residual evaluation function used in applying the matrix-free Jacobian with `-snes_mf_operator`
358
359 Logically Collective
360
361 Input Parameters:
362 + dm - `DM` to be used with `SNES`
363 . func - residual evaluation function; see `SNESFunctionFn` for calling sequence
364 - ctx - optional function context
365
366 Level: developer
367
368 Note:
369 If not provided then the function provided with `SNESSetFunction()` is used
370
371 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `DMSNESSetFunction()`, `SNESFunctionFn`
372 @*/
DMSNESSetMFFunction(DM dm,SNESFunctionFn * func,PetscCtx ctx)373 PetscErrorCode DMSNESSetMFFunction(DM dm, SNESFunctionFn *func, PetscCtx ctx)
374 {
375 DMSNES sdm;
376
377 PetscFunctionBegin;
378 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
379 if (func || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm));
380 if (func) sdm->ops->computemffunction = func;
381 if (ctx) sdm->mffunctionctx = ctx;
382 PetscFunctionReturn(PETSC_SUCCESS);
383 }
384
385 /*@C
386 DMSNESGetFunction - get `SNES` residual evaluation function from a `DMSNES` object
387
388 Not Collective
389
390 Input Parameter:
391 . dm - `DM` to be used with `SNES`
392
393 Output Parameters:
394 + f - residual evaluation function; see `SNESFunctionFn` for calling sequence
395 - ctx - context for residual evaluation
396
397 Level: developer
398
399 Note:
400 `SNESGetFunction()` is normally used, but it calls this function internally because the user context is actually
401 associated with the `DM`.
402
403 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `DMSNESSetFunction()`, `SNESSetFunction()`, `SNESFunctionFn`
404 @*/
DMSNESGetFunction(DM dm,SNESFunctionFn ** f,PetscCtxRt ctx)405 PetscErrorCode DMSNESGetFunction(DM dm, SNESFunctionFn **f, PetscCtxRt ctx)
406 {
407 DMSNES sdm;
408
409 PetscFunctionBegin;
410 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
411 PetscCall(DMGetDMSNES(dm, &sdm));
412 if (f) *f = sdm->ops->computefunction;
413 if (ctx) {
414 if (sdm->functionctxcontainer) PetscCall(PetscContainerGetPointer(sdm->functionctxcontainer, ctx));
415 else *(void **)ctx = NULL;
416 }
417 PetscFunctionReturn(PETSC_SUCCESS);
418 }
419
420 /*@C
421 DMSNESSetObjective - Sets the objective function minimized by some of the `SNES` linesearch methods into a `DMSNES` object, used instead of the 2-norm of the residual
422
423 Not Collective
424
425 Input Parameters:
426 + dm - `DM` to be used with `SNES`
427 . obj - objective evaluation routine; see `SNESObjectiveFn` for the calling sequence
428 - ctx - [optional] user-defined context for private data for the objective evaluation routine (may be `NULL`)
429
430 Level: developer
431
432 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESGetObjective()`, `DMSNESSetFunction()`, `SNESObjectiveFn`
433 @*/
DMSNESSetObjective(DM dm,SNESObjectiveFn * obj,PetscCtx ctx)434 PetscErrorCode DMSNESSetObjective(DM dm, SNESObjectiveFn *obj, PetscCtx ctx)
435 {
436 DMSNES sdm;
437
438 PetscFunctionBegin;
439 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
440 if (obj || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm));
441 if (obj) sdm->ops->computeobjective = obj;
442 if (ctx) sdm->objectivectx = ctx;
443 PetscFunctionReturn(PETSC_SUCCESS);
444 }
445
446 /*@C
447 DMSNESGetObjective - Returns the objective function set with `DMSNESSetObjective()`
448
449 Not Collective
450
451 Input Parameter:
452 . dm - `DM` to be used with `SNES`
453
454 Output Parameters:
455 + obj - objective evaluation routine (or `NULL`); see `SNESObjectiveFn` for the calling sequence
456 - ctx - the function context (or `NULL`)
457
458 Level: developer
459
460 Note:
461 `SNESGetFunction()` is normally used, but it calls this function internally because the user context is actually
462 associated with the `DM`.
463
464 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `DMSNESSetObjective()`, `SNESSetFunction()`, `SNESObjectiveFn`
465 @*/
DMSNESGetObjective(DM dm,SNESObjectiveFn ** obj,PetscCtxRt ctx)466 PetscErrorCode DMSNESGetObjective(DM dm, SNESObjectiveFn **obj, PetscCtxRt ctx)
467 {
468 DMSNES sdm;
469
470 PetscFunctionBegin;
471 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
472 PetscCall(DMGetDMSNES(dm, &sdm));
473 if (obj) *obj = sdm->ops->computeobjective;
474 if (ctx) *(void **)ctx = sdm->objectivectx;
475 PetscFunctionReturn(PETSC_SUCCESS);
476 }
477
478 /*@C
479 DMSNESSetNGS - set `SNES` Gauss-Seidel relaxation function into a `DMSNES` object
480
481 Not Collective
482
483 Input Parameters:
484 + dm - `DM` to be used with `SNES`
485 . f - relaxation function, see `SNESGSFunction`
486 - ctx - context for residual evaluation
487
488 Level: developer
489
490 Note:
491 `SNESSetNGS()` is normally used, but it calls this function internally because the user context is actually
492 associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
493 not.
494
495 Developer Note:
496 If `DM` took a more central role at some later date, this could become the primary method of supplying the smoother
497
498 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `DMSNESSetFunction()`, `SNESGSFunction`
499 @*/
DMSNESSetNGS(DM dm,PetscErrorCode (* f)(SNES,Vec,Vec,void *),PetscCtx ctx)500 PetscErrorCode DMSNESSetNGS(DM dm, PetscErrorCode (*f)(SNES, Vec, Vec, void *), PetscCtx ctx)
501 {
502 DMSNES sdm;
503
504 PetscFunctionBegin;
505 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
506 if (f || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm));
507 if (f) sdm->ops->computegs = f;
508 if (ctx) sdm->gsctx = ctx;
509 PetscFunctionReturn(PETSC_SUCCESS);
510 }
511
512 /*@C
513 DMSNESGetNGS - get `SNES` Gauss-Seidel relaxation function from a `DMSNES` object
514
515 Not Collective
516
517 Input Parameter:
518 . dm - `DM` to be used with `SNES`
519
520 Output Parameters:
521 + f - relaxation function which performs Gauss-Seidel sweeps, see `SNESSetNGS()`
522 - ctx - context for residual evaluation
523
524 Level: developer
525
526 Note:
527 `SNESGetNGS()` is normally used, but it calls this function internally because the user context is actually
528 associated with the `DM`.
529
530 Developer Note:
531 This makes the interface consistent regardless of whether the user interacts with a `DM` or
532 not. If `DM` took a more central role at some later date, this could become the primary method of setting the residual.
533
534 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESGetNGS()`, `DMSNESGetJacobian()`, `DMSNESGetFunction()`
535 @*/
DMSNESGetNGS(DM dm,PetscErrorCode (** f)(SNES,Vec,Vec,void *),PetscCtxRt ctx)536 PetscErrorCode DMSNESGetNGS(DM dm, PetscErrorCode (**f)(SNES, Vec, Vec, void *), PetscCtxRt ctx)
537 {
538 DMSNES sdm;
539
540 PetscFunctionBegin;
541 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
542 PetscCall(DMGetDMSNES(dm, &sdm));
543 if (f) *f = sdm->ops->computegs;
544 if (ctx) *(void **)ctx = sdm->gsctx;
545 PetscFunctionReturn(PETSC_SUCCESS);
546 }
547
548 /*@C
549 DMSNESSetJacobian - set `SNES` Jacobian evaluation function into a `DMSNES` object
550
551 Not Collective
552
553 Input Parameters:
554 + dm - `DM` to be used with `SNES`
555 . J - Jacobian evaluation function, see `SNESJacobianFn`
556 - ctx - context for Jacobian evaluation
557
558 Level: developer
559
560 Note:
561 `SNESSetJacobian()` is normally used, but it calls this function internally because the user context is actually
562 associated with the `DM`.
563
564 Developer Note:
565 This makes the interface consistent regardless of whether the user interacts with a `DM` or
566 not. If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
567
568 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESGetJacobian()`, `SNESSetJacobian()`, `SNESJacobianFn`
569 @*/
DMSNESSetJacobian(DM dm,SNESJacobianFn * J,PetscCtx ctx)570 PetscErrorCode DMSNESSetJacobian(DM dm, SNESJacobianFn *J, PetscCtx ctx)
571 {
572 DMSNES sdm;
573
574 PetscFunctionBegin;
575 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
576 if (J || ctx) PetscCall(DMGetDMSNESWrite(dm, &sdm));
577 if (J) sdm->ops->computejacobian = J;
578 if (ctx) {
579 PetscContainer ctxcontainer;
580 PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)sdm), &ctxcontainer));
581 PetscCall(PetscContainerSetPointer(ctxcontainer, ctx));
582 PetscCall(PetscObjectCompose((PetscObject)sdm, "jacobian ctx", (PetscObject)ctxcontainer));
583 sdm->jacobianctxcontainer = ctxcontainer;
584 PetscCall(PetscContainerDestroy(&ctxcontainer));
585 }
586 PetscFunctionReturn(PETSC_SUCCESS);
587 }
588
589 /*@C
590 DMSNESSetJacobianContextDestroy - set `SNES` Jacobian evaluation context destroy function into a `DMSNES` object
591
592 Not Collective
593
594 Input Parameters:
595 + dm - `DM` to be used with `SNES`
596 - f - Jacobian evaluation context destroy function, see `PetscCtxDestroyFn` for its calling sequence
597
598 Level: developer
599
600 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetJacobian()`
601 @*/
DMSNESSetJacobianContextDestroy(DM dm,PetscCtxDestroyFn * f)602 PetscErrorCode DMSNESSetJacobianContextDestroy(DM dm, PetscCtxDestroyFn *f)
603 {
604 DMSNES sdm;
605
606 PetscFunctionBegin;
607 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
608 PetscCall(DMGetDMSNESWrite(dm, &sdm));
609 if (sdm->jacobianctxcontainer) PetscCall(PetscContainerSetCtxDestroy(sdm->jacobianctxcontainer, f));
610 PetscFunctionReturn(PETSC_SUCCESS);
611 }
612
DMSNESUnsetJacobianContext_Internal(DM dm)613 PetscErrorCode DMSNESUnsetJacobianContext_Internal(DM dm)
614 {
615 DMSNES sdm;
616
617 PetscFunctionBegin;
618 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
619 PetscCall(DMGetDMSNESWrite(dm, &sdm));
620 PetscCall(DMSNESUnsetJacobianContext_DMSNES(sdm));
621 PetscFunctionReturn(PETSC_SUCCESS);
622 }
623
624 /*@C
625 DMSNESGetJacobian - get `SNES` Jacobian evaluation function from a `DMSNES` object
626
627 Not Collective
628
629 Input Parameter:
630 . dm - `DM` to be used with `SNES`
631
632 Output Parameters:
633 + J - Jacobian evaluation function; for all calling sequence see `SNESJacobianFn`
634 - ctx - context for residual evaluation
635
636 Level: developer
637
638 Note:
639 `SNESGetJacobian()` is normally used, but it calls this function internally because the user context is actually
640 associated with the `DM`. This makes the interface consistent regardless of whether the user interacts with a `DM` or
641 not.
642
643 Developer Note:
644 If `DM` took a more central role at some later date, this could become the primary method of setting the Jacobian.
645
646 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `SNESJacobianFn`
647 @*/
DMSNESGetJacobian(DM dm,SNESJacobianFn ** J,PetscCtxRt ctx)648 PetscErrorCode DMSNESGetJacobian(DM dm, SNESJacobianFn **J, PetscCtxRt ctx)
649 {
650 DMSNES sdm;
651
652 PetscFunctionBegin;
653 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
654 PetscCall(DMGetDMSNES(dm, &sdm));
655 if (J) *J = sdm->ops->computejacobian;
656 if (ctx) {
657 if (sdm->jacobianctxcontainer) PetscCall(PetscContainerGetPointer(sdm->jacobianctxcontainer, ctx));
658 else *(void **)ctx = NULL;
659 }
660 PetscFunctionReturn(PETSC_SUCCESS);
661 }
662
663 /*@C
664 DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions into a `DMSNES` object
665
666 Not Collective
667
668 Input Parameters:
669 + dm - `DM` to be used with `SNES`
670 . b - RHS evaluation function; see `SNESFunctionFn` for calling sequence
671 . J - Picard matrix evaluation function; see `SNESJacobianFn` for calling sequence
672 - ctx - context for residual and matrix evaluation
673
674 Level: developer
675
676 .seealso: [](ch_snes), `DMSNES`, `SNESSetPicard()`, `DMSNESSetFunction()`, `DMSNESSetJacobian()`, `SNESFunctionFn`, `SNESJacobianFn`
677 @*/
DMSNESSetPicard(DM dm,SNESFunctionFn * b,SNESJacobianFn * J,PetscCtx ctx)678 PetscErrorCode DMSNESSetPicard(DM dm, SNESFunctionFn *b, SNESJacobianFn *J, PetscCtx ctx)
679 {
680 DMSNES sdm;
681
682 PetscFunctionBegin;
683 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
684 PetscCall(DMGetDMSNES(dm, &sdm));
685 if (b) sdm->ops->computepfunction = b;
686 if (J) sdm->ops->computepjacobian = J;
687 if (ctx) sdm->pctx = ctx;
688 PetscFunctionReturn(PETSC_SUCCESS);
689 }
690
691 /*@C
692 DMSNESGetPicard - get `SNES` Picard iteration evaluation functions from a `DMSNES` object
693
694 Not Collective
695
696 Input Parameter:
697 . dm - `DM` to be used with `SNES`
698
699 Output Parameters:
700 + b - RHS evaluation function; see `SNESFunctionFn` for calling sequence
701 . J - Jacobian evaluation function; see `SNESJacobianFn` for calling sequence
702 - ctx - context for residual and matrix evaluation
703
704 Level: developer
705
706 .seealso: [](ch_snes), `DMSNES`, `DMSNESSetContext()`, `SNESSetFunction()`, `DMSNESSetJacobian()`, `SNESFunctionFn`, `SNESJacobianFn`
707 @*/
DMSNESGetPicard(DM dm,SNESFunctionFn ** b,SNESJacobianFn ** J,PetscCtxRt ctx)708 PetscErrorCode DMSNESGetPicard(DM dm, SNESFunctionFn **b, SNESJacobianFn **J, PetscCtxRt ctx)
709 {
710 DMSNES sdm;
711
712 PetscFunctionBegin;
713 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
714 PetscCall(DMGetDMSNES(dm, &sdm));
715 if (b) *b = sdm->ops->computepfunction;
716 if (J) *J = sdm->ops->computepjacobian;
717 if (ctx) *(void **)ctx = sdm->pctx;
718 PetscFunctionReturn(PETSC_SUCCESS);
719 }
720