xref: /petsc/src/snes/utils/dmsnes.c (revision ff35dfed30cd54218cdaf8727a0fd806f9e95d05)
1 #include <petsc-private/snesimpl.h>   /*I "petscsnes.h" I*/
2 #include <petsc-private/dmimpl.h>     /*I "petscdm.h" I*/
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "SNESDMComputeFunction"
6 /*@C
7   SNESDMComputeFunction - This is a universal function evaluation routine that
8   may be used with SNESSetFunction() as long as the user context has a DM
9   as its first record and the user has called DMSetLocalFunction().
10 
11   Collective on SNES
12 
13   Input Parameters:
14 + snes - the SNES context
15 . X - input vector
16 . F - function vector
17 - ptr - pointer to a structure that must have a DM as its first entry.
18         This ptr must have been passed into SNESDMComputeFunction() as the context.
19 
20   Level: intermediate
21 
22 .seealso: DMSetLocalFunction(), DMSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()
23 @*/
24 PetscErrorCode SNESDMComputeFunction(SNES snes, Vec X, Vec F, void *ptr)
25 {
26   DM               dm = *(DM*) ptr;
27   PetscErrorCode (*lf)(DM, Vec, Vec, void *);
28   Vec              localX, localF;
29   PetscInt         N, n;
30   PetscErrorCode   ierr;
31 
32   PetscFunctionBegin;
33   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
35   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
36   if (!dm) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONGSTATE, "Looks like you called SNESSetFromFuntion(snes,SNESDMComputeFunction,) without the DM context");
37   PetscValidHeaderSpecific(dm, DM_CLASSID, 4);
38 
39   /* determine whether X = localX */
40   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
41   ierr = DMGetLocalVector(dm, &localF);CHKERRQ(ierr);
42   ierr = VecZeroEntries(localX);CHKERRQ(ierr);
43   ierr = VecZeroEntries(localF);CHKERRQ(ierr);
44   ierr = VecGetSize(X, &N);CHKERRQ(ierr);
45   ierr = VecGetSize(localX, &n);CHKERRQ(ierr);
46 
47   if (n != N){ /* X != localX */
48     /* Scatter ghost points to local vector, using the 2-step process
49         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
50     */
51     ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
52     ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
53   } else {
54     ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
55     localX = X;
56   }
57   ierr = DMGetLocalFunction(dm, &lf);CHKERRQ(ierr);
58   printf("x ---------------------\n");
59   VecView(X,0);
60   printf("localx --------------------\n");
61   VecView(localX,0);
62   ierr = (*lf)(dm, localX, localF, ptr);CHKERRQ(ierr);
63   if (n != N){
64     ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
65   }
66   printf("localf ------------------\n");
67   VecView(localF,0);
68   ierr = VecZeroEntries(F);CHKERRQ(ierr);
69   ierr = DMLocalToGlobalBegin(dm, localF, ADD_VALUES, F);CHKERRQ(ierr);
70   ierr = DMLocalToGlobalEnd(dm, localF, ADD_VALUES, F);CHKERRQ(ierr);
71   printf("f-----------------------\n");
72   VecView(F,0);
73   ierr = DMRestoreLocalVector(dm, &localF);CHKERRQ(ierr);
74   PetscFunctionReturn(0);
75 }
76 
77 #undef __FUNCT__
78 #define __FUNCT__ "SNESDMComputeJacobian"
79 /*
80   SNESDMComputeJacobian - This is a universal Jacobian evaluation routine that
81   may be used with SNESSetJacobian() as long as the user context has a DM
82   as its first record and the user has called DMSetLocalJacobian().
83 
84   Collective on SNES
85 
86   Input Parameters:
87 + snes - the SNES context
88 . X - input vector
89 . J - Jacobian
90 . B - Jacobian used in preconditioner (usally same as J)
91 . flag - indicates if the matrix changed its structure
92 - ptr - pointer to a structure that must have a DM as its first entry.
93         This ptr must have been passed into SNESDMComputeFunction() as the context.
94 
95   Level: intermediate
96 
97 .seealso: DMSetLocalFunction(), DMSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()
98 */
99 PetscErrorCode SNESDMComputeJacobian(SNES snes, Vec X, Mat *J, Mat *B, MatStructure *flag, void *ptr)
100 {
101   DM               dm = *(DM*) ptr;
102   PetscErrorCode (*lj)(DM, Vec, Mat, Mat, void *);
103   Vec              localX;
104   PetscErrorCode   ierr;
105 
106   PetscFunctionBegin;
107   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
108   ierr = VecZeroEntries(localX);CHKERRQ(ierr);
109   ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
110   ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
111   ierr = DMGetLocalJacobian(dm, &lj);CHKERRQ(ierr);
112   ierr = (*lj)(dm, localX, *J, *B, ptr);CHKERRQ(ierr);
113   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
114   /* Assemble true Jacobian; if it is different */
115   if (*J != *B) {
116     ierr  = MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
117     ierr  = MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
118   }
119   ierr  = MatSetOption(*B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
120   *flag = SAME_NONZERO_PATTERN;
121   PetscFunctionReturn(0);
122 }
123 
124 #undef __FUNCT__
125 #define __FUNCT__ "PetscContainerDestroy_SNESDM"
126 static PetscErrorCode PetscContainerDestroy_SNESDM(void *ctx)
127 {
128   PetscErrorCode ierr;
129   SNESDM sdm = (SNESDM)ctx;
130 
131   PetscFunctionBegin;
132   if (sdm->destroy) {ierr = (*sdm->destroy)(sdm);CHKERRQ(ierr);}
133   ierr = PetscFree(sdm);CHKERRQ(ierr);
134   PetscFunctionReturn(0);
135 }
136 
137 #undef __FUNCT__
138 #define __FUNCT__ "DMCoarsenHook_SNESDM"
139 /* Attaches the SNESDM to the coarse level.
140  * Under what conditions should we copy versus duplicate?
141  */
142 static PetscErrorCode DMCoarsenHook_SNESDM(DM dm,DM dmc,void *ctx)
143 {
144   PetscErrorCode ierr;
145 
146   PetscFunctionBegin;
147   ierr = DMSNESCopyContext(dm,dmc);CHKERRQ(ierr);
148   PetscFunctionReturn(0);
149 }
150 
151 #undef __FUNCT__
152 #define __FUNCT__ "DMRestrictHook_SNESDM"
153 /* This could restrict auxiliary information to the coarse level.
154  */
155 static PetscErrorCode DMRestrictHook_SNESDM(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
156 {
157 
158   PetscFunctionBegin;
159   PetscFunctionReturn(0);
160 }
161 
162 #undef __FUNCT__
163 #define __FUNCT__ "DMRefineHook_SNESDM"
164 static PetscErrorCode DMRefineHook_SNESDM(DM dm,DM dmf,void *ctx)
165 {
166   PetscErrorCode ierr;
167 
168   PetscFunctionBegin;
169   ierr = DMSNESCopyContext(dm,dmf);CHKERRQ(ierr);
170   PetscFunctionReturn(0);
171 }
172 
173 #undef __FUNCT__
174 #define __FUNCT__ "DMInterpolateHook_SNESDM"
175 /* This could restrict auxiliary information to the coarse level.
176  */
177 static PetscErrorCode DMInterpolateHook_SNESDM(DM dm,Mat Interp,DM dmf,void *ctx)
178 {
179 
180   PetscFunctionBegin;
181   PetscFunctionReturn(0);
182 }
183 
184 #undef __FUNCT__
185 #define __FUNCT__ "DMSNESGetContext"
186 /*@C
187    DMSNESGetContext - get read-only private SNESDM context from a DM
188 
189    Not Collective
190 
191    Input Argument:
192 .  dm - DM to be used with SNES
193 
194    Output Argument:
195 .  snesdm - private SNESDM context
196 
197    Level: developer
198 
199    Notes:
200    Use DMSNESGetContextWrite() if write access is needed. The DMSNESSetXXX API should be used wherever possible.
201 
202 .seealso: DMSNESGetContextWrite()
203 @*/
204 PetscErrorCode DMSNESGetContext(DM dm,SNESDM *snesdm)
205 {
206   PetscErrorCode ierr;
207   PetscContainer container;
208   SNESDM         sdm;
209 
210   PetscFunctionBegin;
211   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
212   ierr = PetscObjectQuery((PetscObject)dm,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr);
213   if (container) {
214     ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr);
215   } else {
216     ierr = PetscInfo(dm,"Creating new SNESDM\n");CHKERRQ(ierr);
217     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr);
218     ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr);
219     ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr);
220     ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr);
221     ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr);
222     ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr);
223     ierr = DMRefineHookAdd(dm,DMRefineHook_SNESDM,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
224     ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr);
225     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
226   }
227   PetscFunctionReturn(0);
228 }
229 
230 #undef __FUNCT__
231 #define __FUNCT__ "DMSNESGetContextWrite"
232 /*@C
233    DMSNESGetContextWrite - get write access to private SNESDM context from a DM
234 
235    Not Collective
236 
237    Input Argument:
238 .  dm - DM to be used with SNES
239 
240    Output Argument:
241 .  snesdm - private SNESDM context
242 
243    Level: developer
244 
245 .seealso: DMSNESGetContext()
246 @*/
247 PetscErrorCode DMSNESGetContextWrite(DM dm,SNESDM *snesdm)
248 {
249   PetscErrorCode ierr;
250   SNESDM         sdm;
251 
252   PetscFunctionBegin;
253   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
254   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
255   if (!sdm->originaldm) sdm->originaldm = dm;
256   if (sdm->originaldm != dm) {  /* Copy on write */
257     PetscContainer container;
258     SNESDM         oldsdm = sdm;
259     ierr = PetscInfo(dm,"Copying SNESDM due to write\n");CHKERRQ(ierr);
260     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr);
261     ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr);
262     ierr = PetscMemcpy(sdm,oldsdm,sizeof(*sdm));CHKERRQ(ierr);
263     ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr);
264     ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr);
265     ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr);
266     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
267     /* implementation specific copy hooks */
268     if (sdm->duplicate) {ierr = (*sdm->duplicate)(oldsdm,dm);CHKERRQ(ierr);}
269   }
270   *snesdm = sdm;
271   PetscFunctionReturn(0);
272 }
273 
274 #undef __FUNCT__
275 #define __FUNCT__ "DMSNESCopyContext"
276 /*@C
277    DMSNESCopyContext - copies a DM context to a new DM
278 
279    Logically Collective
280 
281    Input Arguments:
282 +  dmsrc - DM to obtain context from
283 -  dmdest - DM to add context to
284 
285    Level: developer
286 
287    Note:
288    The context is copied by reference. This function does not ensure that a context exists.
289 
290 .seealso: DMSNESGetContext(), SNESSetDM()
291 @*/
292 PetscErrorCode DMSNESCopyContext(DM dmsrc,DM dmdest)
293 {
294   PetscErrorCode ierr;
295   PetscContainer container;
296 
297   PetscFunctionBegin;
298   PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1);
299   PetscValidHeaderSpecific(dmdest,DM_CLASSID,2);
300   ierr = PetscObjectQuery((PetscObject)dmsrc,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr);
301   if (container) {
302     ierr = PetscObjectCompose((PetscObject)dmdest,"SNESDM",(PetscObject)container);CHKERRQ(ierr);
303     ierr = DMCoarsenHookAdd(dmdest,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr);
304     ierr = DMRefineHookAdd(dmdest,DMRefineHook_SNESDM,DMInterpolateHook_SNESDM,PETSC_NULL);CHKERRQ(ierr);
305   }
306   PetscFunctionReturn(0);
307 }
308 
309 #undef __FUNCT__
310 #define __FUNCT__ "DMSNESSetFunction"
311 /*@C
312    DMSNESSetFunction - set SNES residual evaluation function
313 
314    Not Collective
315 
316    Input Arguments:
317 +  dm - DM to be used with SNES
318 .  func - residual evaluation function, see SNESSetFunction() for calling sequence
319 -  ctx - context for residual evaluation
320 
321    Level: advanced
322 
323    Note:
324    SNESSetFunction() is normally used, but it calls this function internally because the user context is actually
325    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
326    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
327 
328 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
329 @*/
330 PetscErrorCode DMSNESSetFunction(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
331 {
332   PetscErrorCode ierr;
333   SNESDM sdm;
334 
335   PetscFunctionBegin;
336   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
337   if (func || ctx) {
338     ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
339   }
340   if (func) sdm->computefunction = func;
341   if (ctx)  sdm->functionctx = ctx;
342   PetscFunctionReturn(0);
343 }
344 
345 #undef __FUNCT__
346 #define __FUNCT__ "DMSNESGetFunction"
347 /*@C
348    DMSNESGetFunction - get SNES residual evaluation function
349 
350    Not Collective
351 
352    Input Argument:
353 .  dm - DM to be used with SNES
354 
355    Output Arguments:
356 +  func - residual evaluation function, see SNESSetFunction() for calling sequence
357 -  ctx - context for residual evaluation
358 
359    Level: advanced
360 
361    Note:
362    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
363    associated with the DM.
364 
365 .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction()
366 @*/
367 PetscErrorCode DMSNESGetFunction(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
368 {
369   PetscErrorCode ierr;
370   SNESDM sdm;
371 
372   PetscFunctionBegin;
373   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
374   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
375   if (func) *func = sdm->computefunction;
376   if (ctx)  *ctx = sdm->functionctx;
377   PetscFunctionReturn(0);
378 }
379 
380 #undef __FUNCT__
381 #define __FUNCT__ "DMSNESSetObjective"
382 /*@C
383    DMSNESSetObjective - set SNES objective evaluation function
384 
385    Not Collective
386 
387    Input Arguments:
388 +  dm - DM to be used with SNES
389 .  func - residual evaluation function, see SNESSetObjective() for calling sequence
390 -  ctx - context for residual evaluation
391 
392    Level: advanced
393 
394 .seealso: DMSNESSetContext(), SNESGetObjective(), DMSNESSetFunction()
395 @*/
396 PetscErrorCode DMSNESSetObjective(DM dm,SNESObjective func,void *ctx)
397 {
398   PetscErrorCode ierr;
399   SNESDM sdm;
400 
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
403   if (func || ctx) {
404     ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
405   }
406   if (func) sdm->computeobjective = func;
407   if (ctx)  sdm->objectivectx = ctx;
408   PetscFunctionReturn(0);
409 }
410 
411 #undef __FUNCT__
412 #define __FUNCT__ "DMSNESGetObjective"
413 /*@C
414    DMSNESGetObjective - get SNES objective evaluation function
415 
416    Not Collective
417 
418    Input Argument:
419 .  dm - DM to be used with SNES
420 
421    Output Arguments:
422 +  func - residual evaluation function, see SNESSetObjective() for calling sequence
423 -  ctx - context for residual evaluation
424 
425    Level: advanced
426 
427    Note:
428    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
429    associated with the DM.
430 
431 .seealso: DMSNESSetContext(), DMSNESSetObjective(), SNESSetFunction()
432 @*/
433 PetscErrorCode DMSNESGetObjective(DM dm,SNESObjective *func,void **ctx)
434 {
435   PetscErrorCode ierr;
436   SNESDM sdm;
437 
438   PetscFunctionBegin;
439   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
440   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
441   if (func) *func = sdm->computeobjective;
442   if (ctx)  *ctx = sdm->objectivectx;
443   PetscFunctionReturn(0);
444 }
445 
446 #undef __FUNCT__
447 #define __FUNCT__ "DMSNESSetGS"
448 /*@C
449    DMSNESSetGS - set SNES Gauss-Seidel relaxation function
450 
451    Not Collective
452 
453    Input Argument:
454 +  dm - DM to be used with SNES
455 .  func - relaxation function, see SNESSetGS() for calling sequence
456 -  ctx - context for residual evaluation
457 
458    Level: advanced
459 
460    Note:
461    SNESSetGS() is normally used, but it calls this function internally because the user context is actually
462    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
463    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
464 
465 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction()
466 @*/
467 PetscErrorCode DMSNESSetGS(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
468 {
469   PetscErrorCode ierr;
470   SNESDM sdm;
471 
472   PetscFunctionBegin;
473   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
474   if (func || ctx) {
475     ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
476   }
477   if (func) sdm->computegs = func;
478   if (ctx)  sdm->gsctx = ctx;
479   PetscFunctionReturn(0);
480 }
481 
482 #undef __FUNCT__
483 #define __FUNCT__ "DMSNESGetGS"
484 /*@C
485    DMSNESGetGS - get SNES Gauss-Seidel relaxation function
486 
487    Not Collective
488 
489    Input Argument:
490 .  dm - DM to be used with SNES
491 
492    Output Arguments:
493 +  func - relaxation function, see SNESSetGS() for calling sequence
494 -  ctx - context for residual evaluation
495 
496    Level: advanced
497 
498    Note:
499    SNESGetGS() is normally used, but it calls this function internally because the user context is actually
500    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
501    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
502 
503 .seealso: DMSNESSetContext(), SNESGetGS(), DMSNESGetJacobian(), DMSNESGetFunction()
504 @*/
505 PetscErrorCode DMSNESGetGS(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
506 {
507   PetscErrorCode ierr;
508   SNESDM sdm;
509 
510   PetscFunctionBegin;
511   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
512   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
513   if (func) *func = sdm->computegs;
514   if (ctx)  *ctx = sdm->gsctx;
515   PetscFunctionReturn(0);
516 }
517 
518 #undef __FUNCT__
519 #define __FUNCT__ "DMSNESSetJacobian"
520 /*@C
521    DMSNESSetJacobian - set SNES Jacobian evaluation function
522 
523    Not Collective
524 
525    Input Argument:
526 +  dm - DM to be used with SNES
527 .  func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
528 -  ctx - context for residual evaluation
529 
530    Level: advanced
531 
532    Note:
533    SNESSetJacobian() is normally used, but it calls this function internally because the user context is actually
534    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
535    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
536 
537 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian()
538 @*/
539 PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
540 {
541   PetscErrorCode ierr;
542   SNESDM         sdm;
543 
544   PetscFunctionBegin;
545   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
546   if (func || ctx) {
547     ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
548   }
549   if (func) sdm->computejacobian = func;
550   if (ctx)  sdm->jacobianctx = ctx;
551   PetscFunctionReturn(0);
552 }
553 
554 #undef __FUNCT__
555 #define __FUNCT__ "DMSNESGetJacobian"
556 /*@C
557    DMSNESGetJacobian - get SNES Jacobian evaluation function
558 
559    Not Collective
560 
561    Input Argument:
562 .  dm - DM to be used with SNES
563 
564    Output Arguments:
565 +  func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
566 -  ctx - context for residual evaluation
567 
568    Level: advanced
569 
570    Note:
571    SNESGetJacobian() is normally used, but it calls this function internally because the user context is actually
572    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
573    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
574 
575 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
576 @*/
577 PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
578 {
579   PetscErrorCode ierr;
580   SNESDM sdm;
581 
582   PetscFunctionBegin;
583   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
584   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
585   if (func) *func = sdm->computejacobian;
586   if (ctx)  *ctx = sdm->jacobianctx;
587   PetscFunctionReturn(0);
588 }
589 
590 #undef __FUNCT__
591 #define __FUNCT__ "DMSNESSetPicard"
592 /*@C
593    DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions.
594 
595    Not Collective
596 
597    Input Argument:
598 +  dm - DM to be used with SNES
599 .  func - RHS evaluation function, see SNESSetFunction() for calling sequence
600 .  pjac - Picard matrix evaluation function, see SNESSetJacobian() for calling sequence
601 -  ctx - context for residual evaluation
602 
603    Level: advanced
604 
605 .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian()
606 @*/
607 PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (*pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
608 {
609   PetscErrorCode ierr;
610   SNESDM sdm;
611 
612   PetscFunctionBegin;
613   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
614   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
615   if (pfunc) sdm->computepfunction = pfunc;
616   if (pjac)  sdm->computepjacobian = pjac;
617   if (ctx)   sdm->pctx             = ctx;
618   PetscFunctionReturn(0);
619 }
620 
621 
622 #undef __FUNCT__
623 #define __FUNCT__ "DMSNESGetPicard"
624 /*@C
625    DMSNESGetPicard - get SNES Picard iteration evaluation functions
626 
627    Not Collective
628 
629    Input Argument:
630 .  dm - DM to be used with SNES
631 
632    Output Arguments:
633 +  pfunc - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
634 .  pjac  - RHS evaluation function, see SNESSetFunction() for calling sequence
635 -  ctx - context for residual evaluation
636 
637    Level: advanced
638 
639 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
640 @*/
641 PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (**pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
642 {
643   PetscErrorCode ierr;
644   SNESDM sdm;
645 
646   PetscFunctionBegin;
647   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
648   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
649   if (pfunc) *pfunc = sdm->computepfunction;
650   if (pjac) *pjac   = sdm->computepjacobian;
651   if (ctx)  *ctx    = sdm->pctx;
652   PetscFunctionReturn(0);
653 }
654 
655 
656 #undef __FUNCT__
657 #define __FUNCT__ "SNESDefaultComputeFunction_DMLegacy"
658 static PetscErrorCode SNESDefaultComputeFunction_DMLegacy(SNES snes,Vec X,Vec F,void *ctx)
659 {
660   PetscErrorCode ierr;
661   DM             dm;
662 
663   PetscFunctionBegin;
664   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
665   ierr = DMComputeFunction(dm,X,F);CHKERRQ(ierr);
666   PetscFunctionReturn(0);
667 }
668 
669 #undef __FUNCT__
670 #define __FUNCT__ "SNESDefaultComputeJacobian_DMLegacy"
671 static PetscErrorCode SNESDefaultComputeJacobian_DMLegacy(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx)
672 {
673   PetscErrorCode ierr;
674   DM             dm;
675 
676   PetscFunctionBegin;
677   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
678   ierr = DMComputeJacobian(dm,X,*A,*B,mstr);CHKERRQ(ierr);
679   PetscFunctionReturn(0);
680 }
681 
682 #undef __FUNCT__
683 #define __FUNCT__ "DMSNESSetUpLegacy"
684 /* Sets up calling of legacy DM routines */
685 PetscErrorCode DMSNESSetUpLegacy(DM dm)
686 {
687   PetscErrorCode ierr;
688   SNESDM         sdm;
689 
690   PetscFunctionBegin;
691   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
692   if (!sdm->computefunction) {ierr = DMSNESSetFunction(dm,SNESDefaultComputeFunction_DMLegacy,PETSC_NULL);CHKERRQ(ierr);}
693   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
694   if (!sdm->computejacobian) {
695     if (dm->ops->functionj) {
696       ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobian_DMLegacy,PETSC_NULL);CHKERRQ(ierr);
697     } else {
698       ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobianColor,PETSC_NULL);CHKERRQ(ierr);
699     }
700   }
701   PetscFunctionReturn(0);
702 }
703 
704 /* block functions */
705 
706 #undef __FUNCT__
707 #define __FUNCT__ "DMSNESSetBlockFunction"
708 /*@C
709    DMSNESSetBlockFunction - set SNES residual evaluation function
710 
711    Not Collective
712 
713    Input Arguments:
714 +  dm - DM to be used with SNES
715 .  func - residual evaluation function, see SNESSetFunction() for calling sequence
716 -  ctx - context for residual evaluation
717 
718    Level: developer
719 
720    Note:
721    Mostly for use in DM implementations and transferred to a block function rather than being called from here.
722 
723 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
724 @*/
725 PetscErrorCode DMSNESSetBlockFunction(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
726 {
727   PetscErrorCode ierr;
728   SNESDM sdm;
729 
730   PetscFunctionBegin;
731   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
732   if (func || ctx) {
733     ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
734   }
735   if (func) sdm->computeblockfunction = func;
736   if (ctx)  sdm->blockfunctionctx = ctx;
737   PetscFunctionReturn(0);
738 }
739 
740 #undef __FUNCT__
741 #define __FUNCT__ "DMSNESGetBlockFunction"
742 /*@C
743    DMSNESGetBlockFunction - get SNES residual evaluation function
744 
745    Not Collective
746 
747    Input Argument:
748 .  dm - DM to be used with SNES
749 
750    Output Arguments:
751 +  func - residual evaluation function, see SNESSetFunction() for calling sequence
752 -  ctx - context for residual evaluation
753 
754    Level: developer
755 
756 .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction()
757 @*/
758 PetscErrorCode DMSNESGetBlockFunction(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
759 {
760   PetscErrorCode ierr;
761   SNESDM sdm;
762 
763   PetscFunctionBegin;
764   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
765   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
766   if (func) *func = sdm->computeblockfunction;
767   if (ctx)  *ctx = sdm->blockfunctionctx;
768   PetscFunctionReturn(0);
769 }
770 
771 
772 #undef __FUNCT__
773 #define __FUNCT__ "DMSNESSetBlockJacobian"
774 /*@C
775    DMSNESSetJacobian - set SNES Jacobian evaluation function
776 
777    Not Collective
778 
779    Input Argument:
780 +  dm - DM to be used with SNES
781 .  func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
782 -  ctx - context for residual evaluation
783 
784    Level: advanced
785 
786    Note:
787    Mostly for use in DM implementations and transferred to a block function rather than being called from here.
788 
789 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian()
790 @*/
791 PetscErrorCode DMSNESSetBlockJacobian(DM dm,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
792 {
793   PetscErrorCode ierr;
794   SNESDM sdm;
795 
796   PetscFunctionBegin;
797   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
798   if (func || ctx) {
799     ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
800   }
801   if (func) sdm->computeblockjacobian = func;
802   if (ctx)  sdm->blockjacobianctx = ctx;
803   PetscFunctionReturn(0);
804 }
805 
806 #undef __FUNCT__
807 #define __FUNCT__ "DMSNESGetBlockJacobian"
808 /*@C
809    DMSNESGetBlockJacobian - get SNES Jacobian evaluation function
810 
811    Not Collective
812 
813    Input Argument:
814 .  dm - DM to be used with SNES
815 
816    Output Arguments:
817 +  func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
818 -  ctx - context for residual evaluation
819 
820    Level: advanced
821 
822 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
823 @*/
824 PetscErrorCode DMSNESGetBlockJacobian(DM dm,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
825 {
826   PetscErrorCode ierr;
827   SNESDM sdm;
828 
829   PetscFunctionBegin;
830   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
831   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
832   if (func) *func = sdm->computeblockjacobian;
833   if (ctx)  *ctx = sdm->blockjacobianctx;
834   PetscFunctionReturn(0);
835 }
836